Add clarification, as suggested by Nick

This commit is contained in:
Antoine Pitrou 2010-11-16 17:33:07 +00:00
parent 37d8aa6639
commit 9677bf7d5d
1 changed files with 45 additions and 11 deletions

View File

@ -167,11 +167,31 @@ Compatibility strategy
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 **useful compatibility**,
and define as follows:
a narrower type of compatibility, which we will call *useful compatibility*.
* *useful compatibility* doesn't make exception catching any narrower, but
it can be broader for *naïve* exception-catching code. Given the following
For this we first must explain what we will call *careful* and *careless*
exception handling. *Careless* (or "naïve") code is defined as code which
blindly catches either of ``OSError``, ``IOError``, ``socket.error``,
``mmap.error``, ``WindowsError``, ``select.error`` without cheking the ``errno``
attribute. This is because such exception types are much too broad to signify
anything. Either 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.
(moreover, the use of certain of these exceptions is irregular; `Appendix B`_
exposes the case of the `select`_ module, which raises different exceptions
depending on the implementation)
*Careful* code is defined as code which, when catching any of the above
exceptions, examines the ``errno`` attribute to determine the actual error
condition and takes action depending on it.
The we can define *useful compatibility* as follows:
* useful compatibility doesn't make exception catching any narrower, but
it can be broader for *careless* 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::
@ -180,7 +200,7 @@ and define as follows:
except OSError:
pass
* *useful compatibility* doesn't alter the behaviour of *careful*
* useful compatibility doesn't alter the behaviour of *careful*
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::
@ -191,13 +211,13 @@ and define as follows:
if e.errno != errno.ENOENT:
raise
The rationale for this compromise is that careless (or "naïve") 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.
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.
Careful code should not be penalized.
Careful code, on the other hand, should not be penalized. Actually, one
purpose of this PEP is to ease writing careful code.
.. _Step 1:
@ -481,6 +501,20 @@ The moratorium in effect on language builtins means this PEP has little
chance to be accepted for Python 3.2.
Implementation
==============
A reference implementation has been started in ``branches/pep-3151`` in the
Python SVN repository. For now only `Step 1`_ is implemented, and without
the deprecation warnings. However, it shows that coalescing the exception
types doesn't produce any significant annoyance in the standard library.
The only observed trouble is with the respective constructors of ``IOError``
and ``WindowsError``, which are slightly incompatible. The way it is solved
is by keeping the ``IOError`` semantics and adding a fourth optional argument
to allow passing the Windows error code (which is different from the POSIX
errno). All ``PyErr_SetFromWindowsErr*`` functions still do the right thing.
Possible alternative
====================