python-peps/pep-3151/index.html

1107 lines
88 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 3151 Reworking the OS and IO exception hierarchy | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-3151/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 3151 Reworking the OS and IO exception hierarchy | peps.python.org'>
<meta property="og:description" content="The standard exception hierarchy is an important part of the Python language. It has two defining qualities: it is both generic and selective. Generic in that the same exception type can be raised - and handled - regardless of the context (for example...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-3151/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="The standard exception hierarchy is an important part of the Python language. It has two defining qualities: it is both generic and selective. Generic in that the same exception type can be raised - and handled - regardless of the context (for example...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 3151</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 3151 Reworking the OS and IO exception hierarchy</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Antoine Pitrou &lt;solipsis&#32;&#97;t&#32;pitrou.net&gt;</dd>
<dt class="field-even">BDFL-Delegate<span class="colon">:</span></dt>
<dd class="field-even">Barry Warsaw</dd>
<dt class="field-odd">Status<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-even">Type<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-odd">Created<span class="colon">:</span></dt>
<dd class="field-odd">21-Jul-2010</dd>
<dt class="field-even">Python-Version<span class="colon">:</span></dt>
<dd class="field-even">3.3</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd"><p></p></dd>
<dt class="field-even">Resolution<span class="colon">:</span></dt>
<dd class="field-even"><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2011-October/114033.html">Python-Dev message</a></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a><ul>
<li><a class="reference internal" href="#confusing-set-of-os-related-exceptions">Confusing set of OS-related exceptions</a></li>
<li><a class="reference internal" href="#lack-of-fine-grained-exceptions">Lack of fine-grained exceptions</a></li>
</ul>
</li>
<li><a class="reference internal" href="#compatibility-strategy">Compatibility strategy</a></li>
<li><a class="reference internal" href="#step-1-coalesce-exception-types">Step 1: coalesce exception types</a><ul>
<li><a class="reference internal" href="#justification">Justification</a></li>
<li><a class="reference internal" href="#exception-attributes">Exception attributes</a></li>
<li><a class="reference internal" href="#deprecation-of-names">Deprecation of names</a><ul>
<li><a class="reference internal" href="#built-in-exceptions">built-in exceptions</a></li>
<li><a class="reference internal" href="#module-level-exceptions">module-level exceptions</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#step-2-define-additional-subclasses">Step 2: define additional subclasses</a><ul>
<li><a class="reference internal" href="#prerequisite">Prerequisite</a></li>
<li><a class="reference internal" href="#new-exception-classes">New exception classes</a></li>
<li><a class="reference internal" href="#naming">Naming</a></li>
<li><a class="reference internal" href="#id2">Exception attributes</a></li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
</ul>
</li>
<li><a class="reference internal" href="#possible-objections">Possible objections</a><ul>
<li><a class="reference internal" href="#namespace-pollution">Namespace pollution</a></li>
</ul>
</li>
<li><a class="reference internal" href="#earlier-discussion">Earlier discussion</a></li>
<li><a class="reference internal" href="#id4">Implementation</a></li>
<li><a class="reference internal" href="#possible-alternative">Possible alternative</a><ul>
<li><a class="reference internal" href="#pattern-matching">Pattern matching</a></li>
</ul>
</li>
<li><a class="reference internal" href="#exceptions-ignored-by-this-pep">Exceptions ignored by this PEP</a></li>
<li><a class="reference internal" href="#appendix-a-survey-of-common-errnos">Appendix A: Survey of common errnos</a><ul>
<li><a class="reference internal" href="#common-errnos-with-oserror">Common errnos with OSError</a></li>
<li><a class="reference internal" href="#common-errnos-with-ioerror">Common errnos with IOError</a></li>
<li><a class="reference internal" href="#common-errnos-with-socket-error">Common errnos with socket.error</a></li>
<li><a class="reference internal" href="#common-errnos-with-select-error">Common errnos with select.error</a></li>
</ul>
</li>
<li><a class="reference internal" href="#appendix-b-survey-of-raised-os-and-io-errors">Appendix B: Survey of raised OS and IO errors</a><ul>
<li><a class="reference internal" href="#about-vmserror">About VMSError</a></li>
<li><a class="reference internal" href="#interpreter-core">Interpreter core</a></li>
<li><a class="reference internal" href="#standard-library">Standard library</a><ul>
<li><a class="reference internal" href="#bz2">bz2</a></li>
<li><a class="reference internal" href="#curses">curses</a></li>
<li><a class="reference internal" href="#dbm-gnu-dbm-ndbm">dbm.gnu, dbm.ndbm</a></li>
<li><a class="reference internal" href="#fcntl">fcntl</a></li>
<li><a class="reference internal" href="#imp-module">imp module</a></li>
<li><a class="reference internal" href="#io-module">io module</a></li>
<li><a class="reference internal" href="#mmap">mmap</a></li>
<li><a class="reference internal" href="#multiprocessing">multiprocessing</a></li>
<li><a class="reference internal" href="#os-posix">os / posix</a></li>
<li><a class="reference internal" href="#ossaudiodev">ossaudiodev</a></li>
<li><a class="reference internal" href="#readline">readline</a></li>
<li><a class="reference internal" href="#select">select</a></li>
<li><a class="reference internal" href="#signal">signal</a></li>
<li><a class="reference internal" href="#socket">socket</a></li>
<li><a class="reference internal" href="#sys">sys</a></li>
<li><a class="reference internal" href="#time">time</a></li>
<li><a class="reference internal" href="#zipimport">zipimport</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#acknowledgments">Acknowledgments</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>The standard exception hierarchy is an important part of the Python
language. It has two defining qualities: it is both generic and
selective. Generic in that the same exception type can be raised
- and handled - regardless of the context (for example, whether you are
trying to add something to an integer, to call a string method, or to write
an object on a socket, a TypeError will be raised for bad argument types).
Selective in that it allows the user to easily handle (silence, examine,
process, store or encapsulate…) specific kinds of error conditions
while letting other errors bubble up to higher calling contexts. For
example, you can choose to catch ZeroDivisionErrors without affecting
the default handling of other ArithmeticErrors (such as OverflowErrors).</p>
<p>This PEP proposes changes to a part of the exception hierarchy in
order to better embody the qualities mentioned above: the errors
related to operating system calls (OSError, IOError, mmap.error,
select.error, and all their subclasses).</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<section id="confusing-set-of-os-related-exceptions">
<h3><a class="toc-backref" href="#confusing-set-of-os-related-exceptions" role="doc-backlink">Confusing set of OS-related exceptions</a></h3>
<p>OS-related (or system call-related) exceptions are currently a diversity
of classes, arranged in the following sub-hierarchies:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">+--</span> <span class="ne">EnvironmentError</span>
<span class="o">+--</span> <span class="ne">IOError</span>
<span class="o">+--</span> <span class="n">io</span><span class="o">.</span><span class="n">BlockingIOError</span>
<span class="o">+--</span> <span class="n">io</span><span class="o">.</span><span class="n">UnsupportedOperation</span> <span class="p">(</span><span class="n">also</span> <span class="n">inherits</span> <span class="kn">from</span> <span class="nn">ValueError</span><span class="p">)</span>
<span class="o">+--</span> <span class="n">socket</span><span class="o">.</span><span class="n">error</span>
<span class="o">+--</span> <span class="n">socket</span><span class="o">.</span><span class="n">gaierror</span>
<span class="o">+--</span> <span class="n">socket</span><span class="o">.</span><span class="n">herror</span>
<span class="o">+--</span> <span class="n">socket</span><span class="o">.</span><span class="n">timeout</span>
<span class="o">+--</span> <span class="ne">OSError</span>
<span class="o">+--</span> <span class="ne">VMSError</span>
<span class="o">+--</span> <span class="ne">WindowsError</span>
<span class="o">+--</span> <span class="n">mmap</span><span class="o">.</span><span class="n">error</span>
<span class="o">+--</span> <span class="n">select</span><span class="o">.</span><span class="n">error</span>
</pre></div>
</div>
<p>While some of these distinctions can be explained by implementation
considerations, they are often not very logical at a higher level. The
line separating OSError and IOError, for example, is often blurry. Consider
the following:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s2">&quot;fff&quot;</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">OSError</span>: <span class="n">[Errno 2] No such file or directory: &#39;fff&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">open</span><span class="p">(</span><span class="s2">&quot;fff&quot;</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">IOError</span>: <span class="n">[Errno 2] No such file or directory: &#39;fff&#39;</span>
</pre></div>
</div>
<p>The same error condition (a non-existing file) gets cast as two different
exceptions depending on which library function was called. The reason
for this is that the <code class="docutils literal notranslate"><span class="pre">os</span></code> module exclusively raises OSError (or its
subclass WindowsError) while the <code class="docutils literal notranslate"><span class="pre">io</span></code> module mostly raises IOError.
However, the user is interested in the nature of the error, not in which
part of the interpreter it comes from (since the latter is obvious from
reading the traceback message or application source code).</p>
<p>In fact, it is hard to think of any situation where OSError should be
caught but not IOError, or the reverse.</p>
<p>A further proof of the ambiguity of this segmentation is that the standard
library itself sometimes has problems deciding. For example, in the
<code class="docutils literal notranslate"><span class="pre">select</span></code> module, similar failures will raise <code class="docutils literal notranslate"><span class="pre">select.error</span></code>, <code class="docutils literal notranslate"><span class="pre">OSError</span></code>
or <code class="docutils literal notranslate"><span class="pre">IOError</span></code> depending on whether you are using select(), a poll object,
a kqueue object, or an epoll object. This makes user code uselessly
complicated since it has to be prepared to catch various exception types,
depending on which exact implementation of a single primitive it chooses
to use at runtime.</p>
<p>As for WindowsError, it seems to be a pointless distinction. First, it
only exists on Windows systems, which requires tedious compatibility code
in cross-platform applications (such code can be found in <code class="docutils literal notranslate"><span class="pre">Lib/shutil.py</span></code>).
Second, it inherits from OSError and is raised for similar errors as OSError
is raised for on other systems. Third, the user wanting access to low-level
exception specifics has to examine the <code class="docutils literal notranslate"><span class="pre">errno</span></code> or <code class="docutils literal notranslate"><span class="pre">winerror</span></code> attribute
anyway.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p><a class="reference internal" href="#pep-3151-appendix-b">Appendix B</a> surveys the use of the
various exception types across the interpreter and the standard library.</p>
</div>
</section>
<section id="lack-of-fine-grained-exceptions">
<h3><a class="toc-backref" href="#lack-of-fine-grained-exceptions" role="doc-backlink">Lack of fine-grained exceptions</a></h3>
<p>The current variety of OS-related exceptions doesnt allow the user to filter
easily for the desired kinds of failures. As an example, consider the task
of deleting a file if it exists. The Look Before You Leap (LBYL) idiom
suffers from an obvious race condition:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">filename</span><span class="p">):</span>
<span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
</pre></div>
</div>
<p>If a file named as <code class="docutils literal notranslate"><span class="pre">filename</span></code> is created by another thread or process
between the calls to <code class="docutils literal notranslate"><span class="pre">os.path.exists</span></code> and <code class="docutils literal notranslate"><span class="pre">os.remove</span></code>, it wont be
deleted. This can produce bugs in the application, or even security issues.</p>
<p>Therefore, the solution is to try to remove the file, and ignore the error
if the file doesnt exist (an idiom known as Easier to Ask Forgiveness
than to get Permission, or EAFP). Careful code will read like the following
(which works under both POSIX and Windows systems):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
<span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">OSError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="k">if</span> <span class="n">e</span><span class="o">.</span><span class="n">errno</span> <span class="o">!=</span> <span class="n">errno</span><span class="o">.</span><span class="n">ENOENT</span><span class="p">:</span>
<span class="k">raise</span>
</pre></div>
</div>
<p>or even:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
<span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">EnvironmentError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="k">if</span> <span class="n">e</span><span class="o">.</span><span class="n">errno</span> <span class="o">!=</span> <span class="n">errno</span><span class="o">.</span><span class="n">ENOENT</span><span class="p">:</span>
<span class="k">raise</span>
</pre></div>
</div>
<p>This is a lot more to type, and also forces the user to remember the various
cryptic mnemonics from the <code class="docutils literal notranslate"><span class="pre">errno</span></code> module. It imposes an additional
cognitive burden and gets tiresome rather quickly. Consequently, many
programmers will instead write the following code, which silences exceptions
too broadly:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
<span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">OSError</span><span class="p">:</span>
<span class="k">pass</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">os.remove</span></code> can raise an OSError not only when the file doesnt exist,
but in other possible situations (for example, the filename points to a
directory, or the current process doesnt have permission to remove
the file), which all indicate bugs in the application logic and therefore
shouldnt be silenced. What the programmer would like to write instead is
something such as:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
<span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">FileNotFoundError</span><span class="p">:</span>
<span class="k">pass</span>
</pre></div>
</div>
</section>
</section>
<section id="compatibility-strategy">
<h2><a class="toc-backref" href="#compatibility-strategy" role="doc-backlink">Compatibility strategy</a></h2>
<p>Reworking the exception hierarchy will obviously change the exact semantics
of at least some existing code. While it is not possible to improve on the
current situation without changing exact semantics, it is possible to define
a narrower type of compatibility, which we will call <em>useful compatibility</em>.</p>
<p>For this we first must explain what we will call <em>careful</em> and <em>careless</em>
exception handling. <em>Careless</em> (or “naïve”) code is defined as code which
blindly catches any of <code class="docutils literal notranslate"><span class="pre">OSError</span></code>, <code class="docutils literal notranslate"><span class="pre">IOError</span></code>, <code class="docutils literal notranslate"><span class="pre">socket.error</span></code>,
<code class="docutils literal notranslate"><span class="pre">mmap.error</span></code>, <code class="docutils literal notranslate"><span class="pre">WindowsError</span></code>, <code class="docutils literal notranslate"><span class="pre">select.error</span></code> without checking the <code class="docutils literal notranslate"><span class="pre">errno</span></code>
attribute. This is because such exception types are much too broad to signify
anything. Any of them can be raised for error conditions as diverse as: a
bad file descriptor (which will usually indicate a programming error), an
unconnected socket (ditto), a socket timeout, a file type mismatch, an invalid
argument, a transmission failure, insufficient permissions, a non-existent
directory, a full filesystem, etc.</p>
<p>(moreover, the use of certain of these exceptions is irregular; <a class="reference internal" href="#pep-3151-appendix-b">Appendix B</a> exposes the case of the <a class="reference internal" href="#select">select</a> module,
which raises different exceptions depending on the implementation)</p>
<p><em>Careful</em> code is defined as code which, when catching any of the above
exceptions, examines the <code class="docutils literal notranslate"><span class="pre">errno</span></code> attribute to determine the actual error
condition and takes action depending on it.</p>
<p>Then we can define <em>useful compatibility</em> as follows:</p>
<ul>
<li>useful compatibility doesnt make exception catching any narrower, but
it can be broader for <em>careless</em> exception-catching code. Given the following
kind of snippet, all exceptions caught before this PEP will also be
caught after this PEP, but the reverse may be false (because the coalescing
of <code class="docutils literal notranslate"><span class="pre">OSError</span></code>, <code class="docutils literal notranslate"><span class="pre">IOError</span></code> and others means the <code class="docutils literal notranslate"><span class="pre">except</span></code> clause throws
a slightly broader net):<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
<span class="o">...</span>
<span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
<span class="o">...</span>
<span class="k">except</span> <span class="ne">OSError</span><span class="p">:</span>
<span class="k">pass</span>
</pre></div>
</div>
</li>
<li>useful compatibility doesnt alter the behaviour of <em>careful</em>
exception-catching code. Given the following kind of snippet, the same
errors should be silenced or re-raised, regardless of whether this PEP
has been implemented or not:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
<span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">OSError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="k">if</span> <span class="n">e</span><span class="o">.</span><span class="n">errno</span> <span class="o">!=</span> <span class="n">errno</span><span class="o">.</span><span class="n">ENOENT</span><span class="p">:</span>
<span class="k">raise</span>
</pre></div>
</div>
</li>
</ul>
<p>The rationale for this compromise is that careless code cant really be
helped, but at least code which “works” wont suddenly raise errors and
crash. This is important since such code is likely to be present in
scripts used as cron tasks or automated system administration programs.</p>
<p>Careful code, on the other hand, should not be penalized. Actually, one
purpose of this PEP is to ease writing careful code.</p>
</section>
<section id="step-1-coalesce-exception-types">
<span id="step-1"></span><h2><a class="toc-backref" href="#step-1-coalesce-exception-types" role="doc-backlink">Step 1: coalesce exception types</a></h2>
<p>The first step of the resolution is to coalesce existing exception types.
The following changes are proposed:</p>
<ul class="simple">
<li>alias both socket.error and select.error to OSError</li>
<li>alias mmap.error to OSError</li>
<li>alias both WindowsError and VMSError to OSError</li>
<li>alias IOError to OSError</li>
<li>coalesce EnvironmentError into OSError</li>
</ul>
<p>Each of these changes doesnt preserve exact compatibility, but it does
preserve <em>useful compatibility</em> (see “compatibility” section above).</p>
<p>Each of these changes can be accepted or refused individually, but of course
it is considered that the greatest impact can be achieved if this first step
is accepted in full. In this case, the IO exception sub-hierarchy would
become:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">+--</span> <span class="ne">OSError</span> <span class="p">(</span><span class="n">replacing</span> <span class="ne">IOError</span><span class="p">,</span> <span class="ne">WindowsError</span><span class="p">,</span> <span class="ne">EnvironmentError</span><span class="p">,</span> <span class="n">etc</span><span class="o">.</span><span class="p">)</span>
<span class="o">+--</span> <span class="n">io</span><span class="o">.</span><span class="n">BlockingIOError</span>
<span class="o">+--</span> <span class="n">io</span><span class="o">.</span><span class="n">UnsupportedOperation</span> <span class="p">(</span><span class="n">also</span> <span class="n">inherits</span> <span class="kn">from</span> <span class="nn">ValueError</span><span class="p">)</span>
<span class="o">+--</span> <span class="n">socket</span><span class="o">.</span><span class="n">gaierror</span>
<span class="o">+--</span> <span class="n">socket</span><span class="o">.</span><span class="n">herror</span>
<span class="o">+--</span> <span class="n">socket</span><span class="o">.</span><span class="n">timeout</span>
</pre></div>
</div>
<section id="justification">
<h3><a class="toc-backref" href="#justification" role="doc-backlink">Justification</a></h3>
<p>Not only does this first step present the user a simpler landscape as
explained in the <a class="reference internal" href="#rationale">rationale</a> section, but it also allows for a better
and more complete resolution of <a class="reference internal" href="#step-2">Step 2</a> (see <a class="reference internal" href="#prerequisite">Prerequisite</a>).</p>
<p>The rationale for keeping <code class="docutils literal notranslate"><span class="pre">OSError</span></code> as the official name for generic
OS-related exceptions is that it, precisely, is more generic than <code class="docutils literal notranslate"><span class="pre">IOError</span></code>.
<code class="docutils literal notranslate"><span class="pre">EnvironmentError</span></code> is more tedious to type and also much lesser-known.</p>
<p>The survey in <a class="reference internal" href="#pep-3151-appendix-b">Appendix B</a> shows that IOError is the
dominant error today in the standard library. As for third-party Python code,
Google Code Search shows IOError being ten times more popular than
EnvironmentError in user code, and three times more popular than OSError
<a class="footnote-reference brackets" href="#id7" id="id1">[3]</a>. However, with no intention to deprecate IOError in the middle
term, the lesser popularity of OSError is not a problem.</p>
</section>
<section id="exception-attributes">
<h3><a class="toc-backref" href="#exception-attributes" role="doc-backlink">Exception attributes</a></h3>
<p>Since WindowsError is coalesced into OSError, the latter gains a <code class="docutils literal notranslate"><span class="pre">winerror</span></code>
attribute under Windows. It is set to None under situations where it is not
meaningful, as is already the case with the <code class="docutils literal notranslate"><span class="pre">errno</span></code>, <code class="docutils literal notranslate"><span class="pre">filename</span></code> and
<code class="docutils literal notranslate"><span class="pre">strerror</span></code> attributes (for example when OSError is raised directly by
Python code).</p>
</section>
<section id="deprecation-of-names">
<h3><a class="toc-backref" href="#deprecation-of-names" role="doc-backlink">Deprecation of names</a></h3>
<p>The following paragraphs outline a possible deprecation strategy for
old exception names. However, it has been decided to keep them as aliases
for the time being. This decision could be revised in time for Python 4.0.</p>
<section id="built-in-exceptions">
<h4><a class="toc-backref" href="#built-in-exceptions" role="doc-backlink">built-in exceptions</a></h4>
<p>Deprecating the old built-in exceptions cannot be done in a straightforward
fashion by intercepting all lookups in the builtins namespace, since these
are performance-critical. We also cannot work at the object level, since
the deprecated names will be aliased to non-deprecated objects.</p>
<p>A solution is to recognize these names at compilation time, and
then emit a separate <code class="docutils literal notranslate"><span class="pre">LOAD_OLD_GLOBAL</span></code> opcode instead of the regular
<code class="docutils literal notranslate"><span class="pre">LOAD_GLOBAL</span></code>. This specialized opcode will handle the output of a
DeprecationWarning (or PendingDeprecationWarning, depending on the policy
decided upon) when the name doesnt exist in the globals namespace, but
only in the builtins one. This will be enough to avoid false positives
(for example if someone defines their own <code class="docutils literal notranslate"><span class="pre">OSError</span></code> in a module), and
false negatives will be rare (for example when someone accesses <code class="docutils literal notranslate"><span class="pre">OSError</span></code>
through the <code class="docutils literal notranslate"><span class="pre">builtins</span></code> module rather than directly).</p>
</section>
<section id="module-level-exceptions">
<h4><a class="toc-backref" href="#module-level-exceptions" role="doc-backlink">module-level exceptions</a></h4>
<p>The above approach cannot be used easily, since it would require
special-casing some modules when compiling code objects. However, these
names are by construction much less visible (they dont appear in the
builtins namespace), and lesser-known too, so we might decide to let them
live in their own namespaces.</p>
</section>
</section>
</section>
<section id="step-2-define-additional-subclasses">
<span id="step-2"></span><h2><a class="toc-backref" href="#step-2-define-additional-subclasses" role="doc-backlink">Step 2: define additional subclasses</a></h2>
<p>The second step of the resolution is to extend the hierarchy by defining
subclasses which will be raised, rather than their parent, for specific
errno values. Which errno values is subject to discussion, but a survey
of existing exception matching practices (see <a class="reference internal" href="#pep-3151-appendix-a">Appendix A</a>) helps us propose a reasonable subset of all values.
Trying to map all errno mnemonics, indeed, seems foolish, pointless,
and would pollute the root namespace.</p>
<p>Furthermore, in a couple of cases, different errno values could raise
the same exception subclass. For example, EAGAIN, EALREADY, EWOULDBLOCK
and EINPROGRESS are all used to signal that an operation on a non-blocking
socket would block (and therefore needs trying again later). They could
therefore all raise an identical subclass and let the user examine the
<code class="docutils literal notranslate"><span class="pre">errno</span></code> attribute if (s)he so desires (see below “exception
attributes”).</p>
<section id="prerequisite">
<h3><a class="toc-backref" href="#prerequisite" role="doc-backlink">Prerequisite</a></h3>
<p><a class="reference internal" href="#step-1">Step 1</a> is a loose prerequisite for this.</p>
<p>Prerequisite, because some errnos can currently be attached to different
exception classes: for example, ENOENT can be attached to both OSError and
IOError, depending on the context. If we dont want to break <em>useful
compatibility</em>, we cant make an <code class="docutils literal notranslate"><span class="pre">except</span> <span class="pre">OSError</span></code> (or IOError) fail to
match an exception where it would succeed today.</p>
<p>Loose, because we could decide for a partial resolution of step 2
if existing exception classes are not coalesced: for example, ENOENT could
raise a hypothetical FileNotFoundError where an IOError was previously
raised, but continue to raise OSError otherwise.</p>
<p>The dependency on step 1 could be totally removed if the new subclasses
used multiple inheritance to match with all of the existing superclasses
(or, at least, OSError and IOError, which are arguable the most prevalent
ones). It would, however, make the hierarchy more complicated and
therefore harder to grasp for the user.</p>
</section>
<section id="new-exception-classes">
<h3><a class="toc-backref" href="#new-exception-classes" role="doc-backlink">New exception classes</a></h3>
<p>The following tentative list of subclasses, along with a description and
the list of errnos mapped to them, is submitted to discussion:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">FileExistsError</span></code>: trying to create a file or directory which already
exists (EEXIST)</li>
<li><code class="docutils literal notranslate"><span class="pre">FileNotFoundError</span></code>: for all circumstances where a file and directory is
requested but doesnt exist (ENOENT)</li>
<li><code class="docutils literal notranslate"><span class="pre">IsADirectoryError</span></code>: file-level operation (open(), os.remove()…)
requested on a directory (EISDIR)</li>
<li><code class="docutils literal notranslate"><span class="pre">NotADirectoryError</span></code>: directory-level operation requested on something
else (ENOTDIR)</li>
<li><code class="docutils literal notranslate"><span class="pre">PermissionError</span></code>: trying to run an operation without the adequate access
rights - for example filesystem permissions (EACCES, EPERM)</li>
<li><code class="docutils literal notranslate"><span class="pre">BlockingIOError</span></code>: an operation would block on an object (e.g. socket) set
for non-blocking operation (EAGAIN, EALREADY, EWOULDBLOCK, EINPROGRESS);
this is the existing <code class="docutils literal notranslate"><span class="pre">io.BlockingIOError</span></code> with an extended role</li>
<li><code class="docutils literal notranslate"><span class="pre">BrokenPipeError</span></code>: trying to write on a pipe while the other end has been
closed, or trying to write on a socket which has been shutdown for writing
(EPIPE, ESHUTDOWN)</li>
<li><code class="docutils literal notranslate"><span class="pre">InterruptedError</span></code>: a system call was interrupted by an incoming signal
(EINTR)</li>
<li><code class="docutils literal notranslate"><span class="pre">ConnectionAbortedError</span></code>: connection attempt aborted by peer (ECONNABORTED)</li>
<li><code class="docutils literal notranslate"><span class="pre">ConnectionRefusedError</span></code>: connection reset by peer (ECONNREFUSED)</li>
<li><code class="docutils literal notranslate"><span class="pre">ConnectionResetError</span></code>: connection reset by peer (ECONNRESET)</li>
<li><code class="docutils literal notranslate"><span class="pre">TimeoutError</span></code>: connection timed out (ETIMEDOUT); this can be re-cast
as a generic timeout exception, replacing <code class="docutils literal notranslate"><span class="pre">socket.timeout</span></code> and also useful
for other types of timeout (for example in Lock.acquire())</li>
<li><code class="docutils literal notranslate"><span class="pre">ChildProcessError</span></code>: operation on a child process failed (ECHILD);
this is raised mainly by the wait() family of functions.</li>
<li><code class="docutils literal notranslate"><span class="pre">ProcessLookupError</span></code>: the given process (as identified by, e.g., its
process id) doesnt exist (ESRCH).</li>
</ul>
<p>In addition, the following exception class is proposed for inclusion:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">ConnectionError</span></code>: a base class for <code class="docutils literal notranslate"><span class="pre">ConnectionAbortedError</span></code>,
<code class="docutils literal notranslate"><span class="pre">ConnectionRefusedError</span></code> and <code class="docutils literal notranslate"><span class="pre">ConnectionResetError</span></code></li>
</ul>
<p>The following drawing tries to sum up the proposed additions, along with
the corresponding errno values (where applicable). The root of the
sub-hierarchy (OSError, assuming <a class="reference internal" href="#step-1">Step 1</a> is accepted in full) is not
shown:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">+--</span> <span class="ne">BlockingIOError</span> <span class="n">EAGAIN</span><span class="p">,</span> <span class="n">EALREADY</span><span class="p">,</span> <span class="n">EWOULDBLOCK</span><span class="p">,</span> <span class="n">EINPROGRESS</span>
<span class="o">+--</span> <span class="ne">ChildProcessError</span> <span class="n">ECHILD</span>
<span class="o">+--</span> <span class="ne">ConnectionError</span>
<span class="o">+--</span> <span class="ne">BrokenPipeError</span> <span class="n">EPIPE</span><span class="p">,</span> <span class="n">ESHUTDOWN</span>
<span class="o">+--</span> <span class="ne">ConnectionAbortedError</span> <span class="n">ECONNABORTED</span>
<span class="o">+--</span> <span class="ne">ConnectionRefusedError</span> <span class="n">ECONNREFUSED</span>
<span class="o">+--</span> <span class="ne">ConnectionResetError</span> <span class="n">ECONNRESET</span>
<span class="o">+--</span> <span class="ne">FileExistsError</span> <span class="n">EEXIST</span>
<span class="o">+--</span> <span class="ne">FileNotFoundError</span> <span class="n">ENOENT</span>
<span class="o">+--</span> <span class="ne">InterruptedError</span> <span class="n">EINTR</span>
<span class="o">+--</span> <span class="ne">IsADirectoryError</span> <span class="n">EISDIR</span>
<span class="o">+--</span> <span class="ne">NotADirectoryError</span> <span class="n">ENOTDIR</span>
<span class="o">+--</span> <span class="ne">PermissionError</span> <span class="n">EACCES</span><span class="p">,</span> <span class="n">EPERM</span>
<span class="o">+--</span> <span class="ne">ProcessLookupError</span> <span class="n">ESRCH</span>
<span class="o">+--</span> <span class="ne">TimeoutError</span> <span class="n">ETIMEDOUT</span>
</pre></div>
</div>
</section>
<section id="naming">
<h3><a class="toc-backref" href="#naming" role="doc-backlink">Naming</a></h3>
<p>Various naming controversies can arise. One of them is whether all
exception class names should end in “<code class="docutils literal notranslate"><span class="pre">Error</span></code>”. In favour is consistency
with the rest of the exception hierarchy, against is concision (especially
with long names such as <code class="docutils literal notranslate"><span class="pre">ConnectionAbortedError</span></code>).</p>
</section>
<section id="id2">
<h3><a class="toc-backref" href="#id2" role="doc-backlink">Exception attributes</a></h3>
<p>In order to preserve <em>useful compatibility</em>, these subclasses should still
set adequate values for the various exception attributes defined on the
superclass (for example <code class="docutils literal notranslate"><span class="pre">errno</span></code>, <code class="docutils literal notranslate"><span class="pre">filename</span></code>, and optionally
<code class="docutils literal notranslate"><span class="pre">winerror</span></code>).</p>
</section>
<section id="implementation">
<h3><a class="toc-backref" href="#implementation" role="doc-backlink">Implementation</a></h3>
<p>Since it is proposed that the subclasses are raised based purely on the
value of <code class="docutils literal notranslate"><span class="pre">errno</span></code>, little or no changes should be required in extension
modules (either standard or third-party).</p>
<p>The first possibility is to adapt the <code class="docutils literal notranslate"><span class="pre">PyErr_SetFromErrno()</span></code> family
of functions (<code class="docutils literal notranslate"><span class="pre">PyErr_SetFromWindowsErr()</span></code> under Windows) to raise the
appropriate OSError subclass. This wouldnt cover, however, Python
code raising OSError directly, using the following idiom (seen in
<code class="docutils literal notranslate"><span class="pre">Lib/tempfile.py</span></code>):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">raise</span> <span class="ne">IOError</span><span class="p">(</span><span class="n">_errno</span><span class="o">.</span><span class="n">EEXIST</span><span class="p">,</span> <span class="s2">&quot;No usable temporary file name found&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>A second possibility, suggested by Marc-Andre Lemburg, is to adapt
<code class="docutils literal notranslate"><span class="pre">OSError.__new__</span></code> to instantiate the appropriate subclass. This has
the benefit of also covering Python code such as the above.</p>
</section>
</section>
<section id="possible-objections">
<h2><a class="toc-backref" href="#possible-objections" role="doc-backlink">Possible objections</a></h2>
<section id="namespace-pollution">
<h3><a class="toc-backref" href="#namespace-pollution" role="doc-backlink">Namespace pollution</a></h3>
<p>Making the exception hierarchy finer-grained makes the root (or builtins)
namespace larger. This is to be moderated, however, as:</p>
<ul class="simple">
<li>only a handful of additional classes are proposed;</li>
<li>while standard exception types live in the root namespace, they are
visually distinguished by the fact that they use the CamelCase convention,
while almost all other builtins use lowercase naming (except True, False,
None, Ellipsis and NotImplemented)</li>
</ul>
<p>An alternative would be to provide a separate module containing the
finer-grained exceptions, but that would defeat the purpose of
encouraging careful code over careless code, since the user would first
have to import the new module instead of using names already accessible.</p>
</section>
</section>
<section id="earlier-discussion">
<h2><a class="toc-backref" href="#earlier-discussion" role="doc-backlink">Earlier discussion</a></h2>
<p>While this is the first time such as formal proposal is made, the idea
has received informal support in the past <a class="footnote-reference brackets" href="#id6" id="id3">[1]</a>; both the introduction
of finer-grained exception classes and the coalescing of OSError and
IOError.</p>
<p>The removal of WindowsError alone has been discussed and rejected
as part of <a class="pep reference internal" href="../pep-0348/#removing-windowserror" title="PEP 348 Exception Reorganization for Python 3.0 § Removing WindowsError">another PEP</a>,
but there seemed to be a consensus that the
distinction with OSError wasnt meaningful. This supports at least its
aliasing with OSError.</p>
</section>
<section id="id4">
<h2><a class="toc-backref" href="#id4" role="doc-backlink">Implementation</a></h2>
<p>The reference implementation has been integrated into Python 3.3.
It was formerly developed in <a class="reference external" href="http://hg.python.org/features/pep-3151/">http://hg.python.org/features/pep-3151/</a> in
branch <code class="docutils literal notranslate"><span class="pre">pep-3151</span></code>, and also tracked on the bug tracker at
<a class="reference external" href="http://bugs.python.org/issue12555">http://bugs.python.org/issue12555</a>.
It has been successfully tested on a variety of systems: Linux, Windows,
OpenIndiana and FreeBSD buildbots.</p>
<p>One source of trouble has been with the respective constructors of <code class="docutils literal notranslate"><span class="pre">OSError</span></code>
and <code class="docutils literal notranslate"><span class="pre">WindowsError</span></code>, which were incompatible. The way it is solved is by
keeping the <code class="docutils literal notranslate"><span class="pre">OSError</span></code> signature and adding a fourth optional argument
to allow passing the Windows error code (which is different from the POSIX
errno). The fourth argument is stored as <code class="docutils literal notranslate"><span class="pre">winerror</span></code> and its POSIX
translation as <code class="docutils literal notranslate"><span class="pre">errno</span></code>. The <code class="docutils literal notranslate"><span class="pre">PyErr_SetFromWindowsErr*</span></code> functions have
been adapted to use the right constructor call.</p>
<p>A slight complication is when the <code class="docutils literal notranslate"><span class="pre">PyErr_SetExcFromWindowsErr*</span></code> functions
are called with <code class="docutils literal notranslate"><span class="pre">OSError</span></code> rather than <code class="docutils literal notranslate"><span class="pre">WindowsError</span></code>: the <code class="docutils literal notranslate"><span class="pre">errno</span></code>
attribute of the exception object would store the Windows error code (such
as 109 for ERROR_BROKEN_PIPE) rather than its POSIX translation (such as 32
for EPIPE), which it does now. For non-socket error codes, this only occurs
in the private <code class="docutils literal notranslate"><span class="pre">_multiprocessing</span></code> module for which there is no compatibility
concern.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>For socket errors, the “POSIX errno” as reflected by the <code class="docutils literal notranslate"><span class="pre">errno</span></code> module
is numerically equal to the <a class="reference external" href="http://msdn.microsoft.com/en-us/library/ms740668%28v=vs.85%29.aspx">Windows Socket error code</a>
returned by the <code class="docutils literal notranslate"><span class="pre">WSAGetLastError</span></code> system call:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">errno</span><span class="o">.</span><span class="n">EWOULDBLOCK</span>
<span class="go">10035</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">errno</span><span class="o">.</span><span class="n">WSAEWOULDBLOCK</span>
<span class="go">10035</span>
</pre></div>
</div>
</div>
</section>
<section id="possible-alternative">
<h2><a class="toc-backref" href="#possible-alternative" role="doc-backlink">Possible alternative</a></h2>
<section id="pattern-matching">
<h3><a class="toc-backref" href="#pattern-matching" role="doc-backlink">Pattern matching</a></h3>
<p>Another possibility would be to introduce an advanced pattern matching
syntax when catching exceptions. For example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
<span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">OSError</span> <span class="k">as</span> <span class="n">e</span> <span class="k">if</span> <span class="n">e</span><span class="o">.</span><span class="n">errno</span> <span class="o">==</span> <span class="n">errno</span><span class="o">.</span><span class="n">ENOENT</span><span class="p">:</span>
<span class="k">pass</span>
</pre></div>
</div>
<p>Several problems with this proposal:</p>
<ul class="simple">
<li>it introduces new syntax, which is perceived by the author to be a heavier
change compared to reworking the exception hierarchy</li>
<li>it doesnt decrease typing effort significantly</li>
<li>it doesnt relieve the programmer from the burden of having to remember
errno mnemonics</li>
</ul>
</section>
</section>
<section id="exceptions-ignored-by-this-pep">
<h2><a class="toc-backref" href="#exceptions-ignored-by-this-pep" role="doc-backlink">Exceptions ignored by this PEP</a></h2>
<p>This PEP ignores <code class="docutils literal notranslate"><span class="pre">EOFError</span></code>, which signals a truncated input stream in
various protocol and file format implementations (for example <code class="docutils literal notranslate"><span class="pre">GzipFile</span></code>).
<code class="docutils literal notranslate"><span class="pre">EOFError</span></code> is not OS- or IO-related, it is a logical error raised at
a higher level.</p>
<p>This PEP also ignores <code class="docutils literal notranslate"><span class="pre">SSLError</span></code>, which is raised by the <code class="docutils literal notranslate"><span class="pre">ssl</span></code> module
in order to propagate errors signalled by the <code class="docutils literal notranslate"><span class="pre">OpenSSL</span></code> library. Ideally,
<code class="docutils literal notranslate"><span class="pre">SSLError</span></code> would benefit from a similar but separate treatment since it
defines its own constants for error types (<code class="docutils literal notranslate"><span class="pre">ssl.SSL_ERROR_WANT_READ</span></code>,
etc.). In Python 3.2, <code class="docutils literal notranslate"><span class="pre">SSLError</span></code> is already replaced with <code class="docutils literal notranslate"><span class="pre">socket.timeout</span></code>
when it signals a socket timeout (see <a class="reference external" href="http://bugs.python.org/issue10272">issue 10272</a>).</p>
<p>Endly, the fate of <code class="docutils literal notranslate"><span class="pre">socket.gaierror</span></code> and <code class="docutils literal notranslate"><span class="pre">socket.herror</span></code> is not settled.
While they would deserve less cryptic names, this can be handled separately
from the exception hierarchy reorganization effort.</p>
</section>
<section id="appendix-a-survey-of-common-errnos">
<span id="pep-3151-appendix-a"></span><h2><a class="toc-backref" href="#appendix-a-survey-of-common-errnos" role="doc-backlink">Appendix A: Survey of common errnos</a></h2>
<p>This is a quick inventory of the various errno mnemonics checked for in
the standard library and its tests, as part of <code class="docutils literal notranslate"><span class="pre">except</span></code> clauses.</p>
<section id="common-errnos-with-oserror">
<h3><a class="toc-backref" href="#common-errnos-with-oserror" role="doc-backlink">Common errnos with OSError</a></h3>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">EBADF</span></code>: bad file descriptor (usually means the file descriptor was
closed)</li>
<li><code class="docutils literal notranslate"><span class="pre">EEXIST</span></code>: file or directory exists</li>
<li><code class="docutils literal notranslate"><span class="pre">EINTR</span></code>: interrupted function call</li>
<li><code class="docutils literal notranslate"><span class="pre">EISDIR</span></code>: is a directory</li>
<li><code class="docutils literal notranslate"><span class="pre">ENOTDIR</span></code>: not a directory</li>
<li><code class="docutils literal notranslate"><span class="pre">ENOENT</span></code>: no such file or directory</li>
<li><code class="docutils literal notranslate"><span class="pre">EOPNOTSUPP</span></code>: operation not supported on socket
(possible confusion with the existing io.UnsupportedOperation)</li>
<li><code class="docutils literal notranslate"><span class="pre">EPERM</span></code>: operation not permitted (when using e.g. os.setuid())</li>
</ul>
</section>
<section id="common-errnos-with-ioerror">
<h3><a class="toc-backref" href="#common-errnos-with-ioerror" role="doc-backlink">Common errnos with IOError</a></h3>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">EACCES</span></code>: permission denied (for filesystem operations)</li>
<li><code class="docutils literal notranslate"><span class="pre">EBADF</span></code>: bad file descriptor (with select.epoll); read operation on a
write-only GzipFile, or vice-versa</li>
<li><code class="docutils literal notranslate"><span class="pre">EBUSY</span></code>: device or resource busy</li>
<li><code class="docutils literal notranslate"><span class="pre">EISDIR</span></code>: is a directory (when trying to open())</li>
<li><code class="docutils literal notranslate"><span class="pre">ENODEV</span></code>: no such device</li>
<li><code class="docutils literal notranslate"><span class="pre">ENOENT</span></code>: no such file or directory (when trying to open())</li>
<li><code class="docutils literal notranslate"><span class="pre">ETIMEDOUT</span></code>: connection timed out</li>
</ul>
</section>
<section id="common-errnos-with-socket-error">
<h3><a class="toc-backref" href="#common-errnos-with-socket-error" role="doc-backlink">Common errnos with socket.error</a></h3>
<p>All these errors may also be associated with a plain IOError, for example
when calling read() on a sockets file descriptor.</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">EAGAIN</span></code>: resource temporarily unavailable (during a non-blocking socket
call except connect())</li>
<li><code class="docutils literal notranslate"><span class="pre">EALREADY</span></code>: connection already in progress (during a non-blocking
connect())</li>
<li><code class="docutils literal notranslate"><span class="pre">EINPROGRESS</span></code>: operation in progress (during a non-blocking connect())</li>
<li><code class="docutils literal notranslate"><span class="pre">EINTR</span></code>: interrupted function call</li>
<li><code class="docutils literal notranslate"><span class="pre">EISCONN</span></code>: the socket is connected</li>
<li><code class="docutils literal notranslate"><span class="pre">ECONNABORTED</span></code>: connection aborted by peer (during an accept() call)</li>
<li><code class="docutils literal notranslate"><span class="pre">ECONNREFUSED</span></code>: connection refused by peer</li>
<li><code class="docutils literal notranslate"><span class="pre">ECONNRESET</span></code>: connection reset by peer</li>
<li><code class="docutils literal notranslate"><span class="pre">ENOTCONN</span></code>: socket not connected</li>
<li><code class="docutils literal notranslate"><span class="pre">ESHUTDOWN</span></code>: cannot send after transport endpoint shutdown</li>
<li><code class="docutils literal notranslate"><span class="pre">EWOULDBLOCK</span></code>: same reasons as <code class="docutils literal notranslate"><span class="pre">EAGAIN</span></code></li>
</ul>
</section>
<section id="common-errnos-with-select-error">
<h3><a class="toc-backref" href="#common-errnos-with-select-error" role="doc-backlink">Common errnos with select.error</a></h3>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">EINTR</span></code>: interrupted function call</li>
</ul>
</section>
</section>
<section id="appendix-b-survey-of-raised-os-and-io-errors">
<span id="pep-3151-appendix-b"></span><h2><a class="toc-backref" href="#appendix-b-survey-of-raised-os-and-io-errors" role="doc-backlink">Appendix B: Survey of raised OS and IO errors</a></h2>
<section id="about-vmserror">
<h3><a class="toc-backref" href="#about-vmserror" role="doc-backlink">About VMSError</a></h3>
<p>VMSError is completely unused by the interpreter core and the standard
library. It was added as part of the OpenVMS patches submitted in 2002
by Jean-François Piéronne <a class="footnote-reference brackets" href="#id8" id="id5">[4]</a>; the motivation for including VMSError was that
it could be raised by third-party packages.</p>
</section>
<section id="interpreter-core">
<h3><a class="toc-backref" href="#interpreter-core" role="doc-backlink">Interpreter core</a></h3>
<p>Handling of PYTHONSTARTUP raises IOError (but the error gets discarded):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ PYTHONSTARTUP=foox ./python
Python 3.2a0 (py3k:82920M, Jul 16 2010, 22:53:23)
[GCC 4.4.3] on linux2
Type &quot;help&quot;, &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information.
Could not open PYTHONSTARTUP
IOError: [Errno 2] No such file or directory: &#39;foox&#39;
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">PyObject_Print()</span></code> raises IOError when ferror() signals an error on the
<code class="docutils literal notranslate"><span class="pre">FILE</span> <span class="pre">*</span></code> parameter (which, in the source tree, is always either stdout or
stderr).</p>
<p>Unicode encoding and decoding using the <code class="docutils literal notranslate"><span class="pre">mbcs</span></code> encoding can raise
WindowsError for some error conditions.</p>
</section>
<section id="standard-library">
<h3><a class="toc-backref" href="#standard-library" role="doc-backlink">Standard library</a></h3>
<section id="bz2">
<h4><a class="toc-backref" href="#bz2" role="doc-backlink">bz2</a></h4>
<p>Raises IOError throughout (OSError is unused):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">bz2</span><span class="o">.</span><span class="n">BZ2File</span><span class="p">(</span><span class="s2">&quot;foox&quot;</span><span class="p">,</span> <span class="s2">&quot;rb&quot;</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">IOError</span>: <span class="n">[Errno 2] No such file or directory</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">bz2</span><span class="o">.</span><span class="n">BZ2File</span><span class="p">(</span><span class="s2">&quot;LICENSE&quot;</span><span class="p">,</span> <span class="s2">&quot;rb&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">IOError</span>: <span class="n">invalid data stream</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">bz2</span><span class="o">.</span><span class="n">BZ2File</span><span class="p">(</span><span class="s2">&quot;/tmp/zzz.bz2&quot;</span><span class="p">,</span> <span class="s2">&quot;wb&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">IOError</span>: <span class="n">file is not ready for reading</span>
</pre></div>
</div>
</section>
<section id="curses">
<h4><a class="toc-backref" href="#curses" role="doc-backlink">curses</a></h4>
<p>Not examined.</p>
</section>
<section id="dbm-gnu-dbm-ndbm">
<h4><a class="toc-backref" href="#dbm-gnu-dbm-ndbm" role="doc-backlink">dbm.gnu, dbm.ndbm</a></h4>
<p>_dbm.error and _gdbm.error inherit from IOError:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">dbm</span><span class="o">.</span><span class="n">gnu</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s2">&quot;foox&quot;</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">_gdbm.error</span>: <span class="n">[Errno 2] No such file or directory</span>
</pre></div>
</div>
</section>
<section id="fcntl">
<h4><a class="toc-backref" href="#fcntl" role="doc-backlink">fcntl</a></h4>
<p>Raises IOError throughout (OSError is unused).</p>
</section>
<section id="imp-module">
<h4><a class="toc-backref" href="#imp-module" role="doc-backlink">imp module</a></h4>
<p>Raises IOError for bad file descriptors:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">imp</span><span class="o">.</span><span class="n">load_source</span><span class="p">(</span><span class="s2">&quot;foo&quot;</span><span class="p">,</span> <span class="s2">&quot;foo&quot;</span><span class="p">,</span> <span class="mi">123</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">IOError</span>: <span class="n">[Errno 9] Bad file descriptor</span>
</pre></div>
</div>
</section>
<section id="io-module">
<h4><a class="toc-backref" href="#io-module" role="doc-backlink">io module</a></h4>
<p>Raises IOError when trying to open a directory under Unix:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">open</span><span class="p">(</span><span class="s2">&quot;Python/&quot;</span><span class="p">,</span> <span class="s2">&quot;r&quot;</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">IOError</span>: <span class="n">[Errno 21] Is a directory: &#39;Python/&#39;</span>
</pre></div>
</div>
<p>Raises IOError or io.UnsupportedOperation (which inherits from the former)
for unsupported operations:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">open</span><span class="p">(</span><span class="s2">&quot;LICENSE&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s2">&quot;bar&quot;</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">IOError</span>: <span class="n">not writable</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">io</span><span class="o">.</span><span class="n">StringIO</span><span class="p">()</span><span class="o">.</span><span class="n">fileno</span><span class="p">()</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">io.UnsupportedOperation</span>: <span class="n">fileno</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">open</span><span class="p">(</span><span class="s2">&quot;LICENSE&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">seek</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">IOError</span>: <span class="n">can&#39;t do nonzero cur-relative seeks</span>
</pre></div>
</div>
<p>Raises either IOError or TypeError when the inferior I/O layer misbehaves
(i.e. violates the API it is expected to implement).</p>
<p>Raises IOError when the underlying OS resource becomes invalid:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s2">&quot;LICENSE&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">os</span><span class="o">.</span><span class="n">close</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">fileno</span><span class="p">())</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">IOError</span>: <span class="n">[Errno 9] Bad file descriptor</span>
</pre></div>
</div>
<p>…or for implementation-specific optimizations:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s2">&quot;LICENSE&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">next</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
<span class="go">&#39;A. HISTORY OF THE SOFTWARE\n&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">f</span><span class="o">.</span><span class="n">tell</span><span class="p">()</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">IOError</span>: <span class="n">telling position disabled by next() call</span>
</pre></div>
</div>
<p>Raises BlockingIOError (inheriting from IOError) when a call on a non-blocking
object would block.</p>
</section>
<section id="mmap">
<h4><a class="toc-backref" href="#mmap" role="doc-backlink">mmap</a></h4>
<p>Under Unix, raises its own <code class="docutils literal notranslate"><span class="pre">mmap.error</span></code> (inheriting from EnvironmentError)
throughout:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">mmap</span><span class="o">.</span><span class="n">mmap</span><span class="p">(</span><span class="mi">123</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">mmap.error</span>: <span class="n">[Errno 9] Bad file descriptor</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">mmap</span><span class="o">.</span><span class="n">mmap</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s2">&quot;/tmp&quot;</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">O_RDONLY</span><span class="p">),</span> <span class="mi">10</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">mmap.error</span>: <span class="n">[Errno 13] Permission denied</span>
</pre></div>
</div>
<p>Under Windows, however, it mostly raises WindowsError (the source code
also shows a few occurrences of <code class="docutils literal notranslate"><span class="pre">mmap.error</span></code>):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">fd</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s2">&quot;LICENSE&quot;</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">O_RDONLY</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">m</span> <span class="o">=</span> <span class="n">mmap</span><span class="o">.</span><span class="n">mmap</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="mi">16384</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">WindowsError</span>: <span class="n">[Error 5] Accès refusé</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">sys</span><span class="o">.</span><span class="n">last_value</span><span class="o">.</span><span class="n">errno</span>
<span class="go">13</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">errno</span><span class="o">.</span><span class="n">errorcode</span><span class="p">[</span><span class="mi">13</span><span class="p">]</span>
<span class="go">&#39;EACCES&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">m</span> <span class="o">=</span> <span class="n">mmap</span><span class="o">.</span><span class="n">mmap</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">4096</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">m</span><span class="o">.</span><span class="n">resize</span><span class="p">(</span><span class="mi">16384</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">WindowsError</span>: <span class="n">[Error 87] Paramètre incorrect</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">sys</span><span class="o">.</span><span class="n">last_value</span><span class="o">.</span><span class="n">errno</span>
<span class="go">22</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">errno</span><span class="o">.</span><span class="n">errorcode</span><span class="p">[</span><span class="mi">22</span><span class="p">]</span>
<span class="go">&#39;EINVAL&#39;</span>
</pre></div>
</div>
</section>
<section id="multiprocessing">
<h4><a class="toc-backref" href="#multiprocessing" role="doc-backlink">multiprocessing</a></h4>
<p>Not examined.</p>
</section>
<section id="os-posix">
<h4><a class="toc-backref" href="#os-posix" role="doc-backlink">os / posix</a></h4>
<p>The <code class="docutils literal notranslate"><span class="pre">os</span></code> (or <code class="docutils literal notranslate"><span class="pre">posix</span></code>) module raises OSError throughout, except under
Windows where WindowsError can be raised instead.</p>
</section>
<section id="ossaudiodev">
<h4><a class="toc-backref" href="#ossaudiodev" role="doc-backlink">ossaudiodev</a></h4>
<p>Raises IOError throughout (OSError is unused):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">ossaudiodev</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s2">&quot;foo&quot;</span><span class="p">,</span> <span class="s2">&quot;r&quot;</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">IOError</span>: <span class="n">[Errno 2] No such file or directory: &#39;foo&#39;</span>
</pre></div>
</div>
</section>
<section id="readline">
<h4><a class="toc-backref" href="#readline" role="doc-backlink">readline</a></h4>
<p>Raises IOError in various file-handling functions:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">readline</span><span class="o">.</span><span class="n">read_history_file</span><span class="p">(</span><span class="s2">&quot;foo&quot;</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">IOError</span>: <span class="n">[Errno 2] No such file or directory</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">readline</span><span class="o">.</span><span class="n">read_init_file</span><span class="p">(</span><span class="s2">&quot;foo&quot;</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">IOError</span>: <span class="n">[Errno 2] No such file or directory</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">readline</span><span class="o">.</span><span class="n">write_history_file</span><span class="p">(</span><span class="s2">&quot;/dev/nonexistent&quot;</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">IOError</span>: <span class="n">[Errno 13] Permission denied</span>
</pre></div>
</div>
</section>
<section id="select">
<h4><a class="toc-backref" href="#select" role="doc-backlink">select</a></h4>
<ul class="simple">
<li>select() and poll objects raise <code class="docutils literal notranslate"><span class="pre">select.error</span></code>, which doesnt inherit from
anything (but poll.modify() raises IOError);</li>
<li>epoll objects raise IOError;</li>
<li>kqueue objects raise both OSError and IOError.</li>
</ul>
<p>As a side-note, not deriving from <code class="docutils literal notranslate"><span class="pre">EnvironmentError</span></code> means <code class="docutils literal notranslate"><span class="pre">select.error</span></code>
does not get the useful <code class="docutils literal notranslate"><span class="pre">errno</span></code> attribute. User code must check <code class="docutils literal notranslate"><span class="pre">args[0]</span></code>
instead:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">signal</span><span class="o">.</span><span class="n">alarm</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="n">select</span><span class="o">.</span><span class="n">select</span><span class="p">([],</span> <span class="p">[],</span> <span class="p">[])</span>
<span class="go">0</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">select.error</span>: <span class="n">(4, &#39;Interrupted system call&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">e</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">last_value</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">e</span>
<span class="go">error(4, &#39;Interrupted system call&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">e</span><span class="o">.</span><span class="n">errno</span> <span class="o">==</span> <span class="n">errno</span><span class="o">.</span><span class="n">EINTR</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">AttributeError</span>: <span class="n">&#39;error&#39; object has no attribute &#39;errno&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">e</span><span class="o">.</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="n">errno</span><span class="o">.</span><span class="n">EINTR</span>
<span class="go">True</span>
</pre></div>
</div>
</section>
<section id="signal">
<h4><a class="toc-backref" href="#signal" role="doc-backlink">signal</a></h4>
<p><code class="docutils literal notranslate"><span class="pre">signal.ItimerError</span></code> inherits from IOError.</p>
</section>
<section id="socket">
<h4><a class="toc-backref" href="#socket" role="doc-backlink">socket</a></h4>
<p><code class="docutils literal notranslate"><span class="pre">socket.error</span></code> inherits from IOError.</p>
</section>
<section id="sys">
<h4><a class="toc-backref" href="#sys" role="doc-backlink">sys</a></h4>
<p><code class="docutils literal notranslate"><span class="pre">sys.getwindowsversion()</span></code> raises WindowsError with a bogus error number
if the <code class="docutils literal notranslate"><span class="pre">GetVersionEx()</span></code> call fails.</p>
</section>
<section id="time">
<h4><a class="toc-backref" href="#time" role="doc-backlink">time</a></h4>
<p>Raises IOError for internal errors in time.time() and time.sleep().</p>
</section>
<section id="zipimport">
<h4><a class="toc-backref" href="#zipimport" role="doc-backlink">zipimport</a></h4>
<p>zipimporter.get_data() can raise IOError.</p>
</section>
</section>
</section>
<section id="acknowledgments">
<h2><a class="toc-backref" href="#acknowledgments" role="doc-backlink">Acknowledgments</a></h2>
<p>Significant input has been received from Alyssa Coghlan.</p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id6" role="doc-footnote">
<dt class="label" id="id6">[<a href="#id3">1</a>]</dt>
<dd>“IO module precisions and exception hierarchy”:
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2009-September/092130.html">https://mail.python.org/pipermail/python-dev/2009-September/092130.html</a></aside>
<aside class="footnote brackets" id="id7" role="doc-footnote">
<dt class="label" id="id7">[<a href="#id1">3</a>]</dt>
<dd>Google Code Search of <code class="docutils literal notranslate"><span class="pre">IOError</span></code> in Python code: <a class="reference external" href="http://www.google.com/codesearch?q=lang%3Apython%20IOError">around 40000 results</a>;
<code class="docutils literal notranslate"><span class="pre">OSError</span></code>: <a class="reference external" href="http://www.google.com/codesearch?q=lang%3Apython%20OSError">around 15200 results</a>;
<code class="docutils literal notranslate"><span class="pre">EnvironmentError</span></code>: <a class="reference external" href="http://www.google.com/codesearch?q=lang%3Apython%20EnvironmentError">around 3000 results</a></aside>
<aside class="footnote brackets" id="id8" role="doc-footnote">
<dt class="label" id="id8">[<a href="#id5">4</a>]</dt>
<dd><a class="reference external" href="http://bugs.python.org/issue614055">http://bugs.python.org/issue614055</a></aside>
</aside>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-3151.rst">https://github.com/python/peps/blob/main/peps/pep-3151.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-3151.rst">2023-10-11 12:05:51 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a><ul>
<li><a class="reference internal" href="#confusing-set-of-os-related-exceptions">Confusing set of OS-related exceptions</a></li>
<li><a class="reference internal" href="#lack-of-fine-grained-exceptions">Lack of fine-grained exceptions</a></li>
</ul>
</li>
<li><a class="reference internal" href="#compatibility-strategy">Compatibility strategy</a></li>
<li><a class="reference internal" href="#step-1-coalesce-exception-types">Step 1: coalesce exception types</a><ul>
<li><a class="reference internal" href="#justification">Justification</a></li>
<li><a class="reference internal" href="#exception-attributes">Exception attributes</a></li>
<li><a class="reference internal" href="#deprecation-of-names">Deprecation of names</a><ul>
<li><a class="reference internal" href="#built-in-exceptions">built-in exceptions</a></li>
<li><a class="reference internal" href="#module-level-exceptions">module-level exceptions</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#step-2-define-additional-subclasses">Step 2: define additional subclasses</a><ul>
<li><a class="reference internal" href="#prerequisite">Prerequisite</a></li>
<li><a class="reference internal" href="#new-exception-classes">New exception classes</a></li>
<li><a class="reference internal" href="#naming">Naming</a></li>
<li><a class="reference internal" href="#id2">Exception attributes</a></li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
</ul>
</li>
<li><a class="reference internal" href="#possible-objections">Possible objections</a><ul>
<li><a class="reference internal" href="#namespace-pollution">Namespace pollution</a></li>
</ul>
</li>
<li><a class="reference internal" href="#earlier-discussion">Earlier discussion</a></li>
<li><a class="reference internal" href="#id4">Implementation</a></li>
<li><a class="reference internal" href="#possible-alternative">Possible alternative</a><ul>
<li><a class="reference internal" href="#pattern-matching">Pattern matching</a></li>
</ul>
</li>
<li><a class="reference internal" href="#exceptions-ignored-by-this-pep">Exceptions ignored by this PEP</a></li>
<li><a class="reference internal" href="#appendix-a-survey-of-common-errnos">Appendix A: Survey of common errnos</a><ul>
<li><a class="reference internal" href="#common-errnos-with-oserror">Common errnos with OSError</a></li>
<li><a class="reference internal" href="#common-errnos-with-ioerror">Common errnos with IOError</a></li>
<li><a class="reference internal" href="#common-errnos-with-socket-error">Common errnos with socket.error</a></li>
<li><a class="reference internal" href="#common-errnos-with-select-error">Common errnos with select.error</a></li>
</ul>
</li>
<li><a class="reference internal" href="#appendix-b-survey-of-raised-os-and-io-errors">Appendix B: Survey of raised OS and IO errors</a><ul>
<li><a class="reference internal" href="#about-vmserror">About VMSError</a></li>
<li><a class="reference internal" href="#interpreter-core">Interpreter core</a></li>
<li><a class="reference internal" href="#standard-library">Standard library</a><ul>
<li><a class="reference internal" href="#bz2">bz2</a></li>
<li><a class="reference internal" href="#curses">curses</a></li>
<li><a class="reference internal" href="#dbm-gnu-dbm-ndbm">dbm.gnu, dbm.ndbm</a></li>
<li><a class="reference internal" href="#fcntl">fcntl</a></li>
<li><a class="reference internal" href="#imp-module">imp module</a></li>
<li><a class="reference internal" href="#io-module">io module</a></li>
<li><a class="reference internal" href="#mmap">mmap</a></li>
<li><a class="reference internal" href="#multiprocessing">multiprocessing</a></li>
<li><a class="reference internal" href="#os-posix">os / posix</a></li>
<li><a class="reference internal" href="#ossaudiodev">ossaudiodev</a></li>
<li><a class="reference internal" href="#readline">readline</a></li>
<li><a class="reference internal" href="#select">select</a></li>
<li><a class="reference internal" href="#signal">signal</a></li>
<li><a class="reference internal" href="#socket">socket</a></li>
<li><a class="reference internal" href="#sys">sys</a></li>
<li><a class="reference internal" href="#time">time</a></li>
<li><a class="reference internal" href="#zipimport">zipimport</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#acknowledgments">Acknowledgments</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-3151.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>