1107 lines
88 KiB
HTML
1107 lines
88 KiB
HTML
|
||
<!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> » </li>
|
||
<li><a href="../pep-0000/">PEP Index</a> » </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 <solipsis at pitrou.net></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">>>> </span><span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s2">"fff"</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></span>
|
||
<span class="gr">OSError</span>: <span class="n">[Errno 2] No such file or directory: 'fff'</span>
|
||
<span class="gp">>>> </span><span class="nb">open</span><span class="p">(</span><span class="s2">"fff"</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></span>
|
||
<span class="gr">IOError</span>: <span class="n">[Errno 2] No such file or directory: 'fff'</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 doesn’t 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 won’t 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 doesn’t 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 doesn’t exist,
|
||
but in other possible situations (for example, the filename points to a
|
||
directory, or the current process doesn’t have permission to remove
|
||
the file), which all indicate bugs in the application logic and therefore
|
||
shouldn’t 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 doesn’t 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 doesn’t 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 can’t really be
|
||
helped, but at least code which “works” won’t 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 doesn’t 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 doesn’t 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 don’t 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 don’t want to break <em>useful
|
||
compatibility</em>, we can’t 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 doesn’t 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) doesn’t 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 wouldn’t 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">"No usable temporary file name found"</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 wasn’t 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">>>> </span><span class="n">errno</span><span class="o">.</span><span class="n">EWOULDBLOCK</span>
|
||
<span class="go">10035</span>
|
||
<span class="gp">>>> </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 doesn’t decrease typing effort significantly</li>
|
||
<li>it doesn’t 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 socket’s 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 "help", "copyright", "credits" or "license" for more information.
|
||
Could not open PYTHONSTARTUP
|
||
IOError: [Errno 2] No such file or directory: 'foox'
|
||
</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">>>> </span><span class="n">bz2</span><span class="o">.</span><span class="n">BZ2File</span><span class="p">(</span><span class="s2">"foox"</span><span class="p">,</span> <span class="s2">"rb"</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></span>
|
||
<span class="gr">IOError</span>: <span class="n">[Errno 2] No such file or directory</span>
|
||
<span class="gp">>>> </span><span class="n">bz2</span><span class="o">.</span><span class="n">BZ2File</span><span class="p">(</span><span class="s2">"LICENSE"</span><span class="p">,</span> <span class="s2">"rb"</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">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></span>
|
||
<span class="gr">IOError</span>: <span class="n">invalid data stream</span>
|
||
<span class="gp">>>> </span><span class="n">bz2</span><span class="o">.</span><span class="n">BZ2File</span><span class="p">(</span><span class="s2">"/tmp/zzz.bz2"</span><span class="p">,</span> <span class="s2">"wb"</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">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></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">>>> </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">"foox"</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></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">>>> </span><span class="n">imp</span><span class="o">.</span><span class="n">load_source</span><span class="p">(</span><span class="s2">"foo"</span><span class="p">,</span> <span class="s2">"foo"</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">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></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">>>> </span><span class="nb">open</span><span class="p">(</span><span class="s2">"Python/"</span><span class="p">,</span> <span class="s2">"r"</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></span>
|
||
<span class="gr">IOError</span>: <span class="n">[Errno 21] Is a directory: 'Python/'</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">>>> </span><span class="nb">open</span><span class="p">(</span><span class="s2">"LICENSE"</span><span class="p">)</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s2">"bar"</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></span>
|
||
<span class="gr">IOError</span>: <span class="n">not writable</span>
|
||
<span class="gp">>>> </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">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></span>
|
||
<span class="gr">io.UnsupportedOperation</span>: <span class="n">fileno</span>
|
||
<span class="gp">>>> </span><span class="nb">open</span><span class="p">(</span><span class="s2">"LICENSE"</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">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></span>
|
||
<span class="gr">IOError</span>: <span class="n">can'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">>>> </span><span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s2">"LICENSE"</span><span class="p">)</span>
|
||
<span class="gp">>>> </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">>>> </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">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></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">>>> </span><span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s2">"LICENSE"</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="nb">next</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
|
||
<span class="go">'A. HISTORY OF THE SOFTWARE\n'</span>
|
||
<span class="gp">>>> </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">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></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">>>> </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">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></span>
|
||
<span class="gr">mmap.error</span>: <span class="n">[Errno 9] Bad file descriptor</span>
|
||
<span class="gp">>>> </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">"/tmp"</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">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></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">>>> </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">"LICENSE"</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">>>> </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">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></span>
|
||
<span class="gr">WindowsError</span>: <span class="n">[Error 5] Accès refusé</span>
|
||
<span class="gp">>>> </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">>>> </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">'EACCES'</span>
|
||
|
||
<span class="gp">>>> </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">>>> </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">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></span>
|
||
<span class="gr">WindowsError</span>: <span class="n">[Error 87] Paramètre incorrect</span>
|
||
<span class="gp">>>> </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">>>> </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">'EINVAL'</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">>>> </span><span class="n">ossaudiodev</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s2">"foo"</span><span class="p">,</span> <span class="s2">"r"</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></span>
|
||
<span class="gr">IOError</span>: <span class="n">[Errno 2] No such file or directory: 'foo'</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">>>> </span><span class="n">readline</span><span class="o">.</span><span class="n">read_history_file</span><span class="p">(</span><span class="s2">"foo"</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></span>
|
||
<span class="gr">IOError</span>: <span class="n">[Errno 2] No such file or directory</span>
|
||
<span class="gp">>>> </span><span class="n">readline</span><span class="o">.</span><span class="n">read_init_file</span><span class="p">(</span><span class="s2">"foo"</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></span>
|
||
<span class="gr">IOError</span>: <span class="n">[Errno 2] No such file or directory</span>
|
||
<span class="gp">>>> </span><span class="n">readline</span><span class="o">.</span><span class="n">write_history_file</span><span class="p">(</span><span class="s2">"/dev/nonexistent"</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></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 doesn’t 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">>>> </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">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></span>
|
||
<span class="gr">select.error</span>: <span class="n">(4, 'Interrupted system call')</span>
|
||
<span class="gp">>>> </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">>>> </span><span class="n">e</span>
|
||
<span class="go">error(4, 'Interrupted system call')</span>
|
||
<span class="gp">>>> </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">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></span>
|
||
<span class="gr">AttributeError</span>: <span class="n">'error' object has no attribute 'errno'</span>
|
||
<span class="gp">>>> </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> |