[Python-ideas] PEP 3151: Reworking the OS and IO exception hierarchy

Gregory P. Smith greg at krypto.org
Sat Jul 24 23:31:42 CEST 2010


On Wed, Jul 21, 2010 at 12:34 PM, Antoine Pitrou <solipsis at pitrou.net>wrote:
>
> Hello,
>
> I would like to propose the following PEP for feedback and review.
> Permanent link to up-to-date version with proper HTML formatting:
> http://www.python.org/dev/peps/pep-3151/
>
> Thank you,
>
> Antoine.
>
> ... ...

>
> New exception classes
> ---------------------
>
> The following tentative list of subclasses, along with a description and
> the list of errnos mapped to them, is submitted to discussion:
>
> * ``FileAlreadyExists``: trying to create a file or directory which already
>  exists (EEXIST)
>
> * ``FileNotFound``: for all circumstances where a file and directory is
>  requested but doesn't exist (ENOENT)
>
> * ``IsADirectory``: file-level operation (open(), os.remove()...) requested
>  on a directory (EISDIR)
>
> * ``NotADirectory``: directory-level operation requested on something else
>  (ENOTDIR)
>
> * ``PermissionDenied``: trying to run an operation without the adequate
> access
>  rights - for example filesystem permissions (EACCESS, optionally EPERM)
>
> * ``BlockingIOError``: an operation would block on an object (e.g. socket)
> set
>  for non-blocking operation (EAGAIN, EALREADY, EWOULDBLOCK, EINPROGRESS);
>  this is the existing ``io.BlockingIOError`` with an extended role
>
> * ``BadFileDescriptor``: operation on an invalid file descriptor (EBADF);
>  the default error message could point out that most causes are that
>  an existing file descriptor has been closed
>
> * ``ConnectionAborted``: connection attempt aborted by peer (ECONNABORTED)
>
> * ``ConnectionRefused``: connection reset by peer (ECONNREFUSED)
>
> * ``ConnectionReset``: connection reset by peer (ECONNRESET)
>
> * ``TimeoutError``: connection timed out (ECONNTIMEOUT); this could be
> re-cast
>  as a generic timeout exception, useful for other types of timeout (for
>  example in Lock.acquire())
>
> This list assumes step 1 is accepted in full; the exception classes
> described above would all derive from the now unified exception type
> OSError.  It will need reworking if a partial version of step 1 is accepted
> instead (again, see appendix A for the current distribution of errnos
> and exception types).
>
>
> Exception attributes
> --------------------
>
> In order to preserve *useful compatibility*, these subclasses should still
> set adequate values for the various exception attributes defined on the
> superclass (for example ``errno``, ``filename``, and optionally
> ``winerror``).
>
> Implementation
> --------------
>
> Since it is proposed that the subclasses are raised based purely on the
> value of ``errno``, little or no changes should be required in extension
> modules (either standard or third-party).  As long as they use the
> ``PyErr_SetFromErrno()`` family of functions (or the
> ``PyErr_SetFromWindowsErr()`` family of functions under Windows), they
> should automatically benefit from the new, finer-grained exception classes.
>
> Library modules written in Python, though, will have to be adapted where
> they currently use the following idiom (seen in ``Lib/tempfile.py``)::
>
>    raise IOError(_errno.EEXIST, "No usable temporary file name found")
>
> Fortunately, such Python code is quite rare since raising OSError or
> IOError
> with an errno value normally happens when interfacing with system calls,
> which is usually done in C extensions.
>
> If there is popular demand, the subroutine choosing an exception type based
> on the errno value could be exposed for use in pure Python.
>
>
> Possible objections
> ===================
>
> Namespace pollution
> -------------------
>
> Making the exception hierarchy finer-grained makes the root (or builtins)
> namespace larger.  This is to be moderated, however, as:
>
> * only a handful of additional classes are proposed;
>
> * 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)
>
> 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.
>

+1 in on this whole PEP!

The EnvrionmentError hierarchy and common errno test code has bothered me
for a while.  While I think the namespace pollution concern is valid I would
suggest adding "Error" to the end of all of the names (your initial proposal
only says "Error" on the end of one of them) as that is consistent with the
bulk of the existing standard exceptions and warnings.  They are unlikely to
conflict with anything other than exceptions people have already defined
themselves in any existing code (which could likely be refactored out after
we officially define these).



>
> Earlier discussion
> ==================
>
> While this is the first time such as formal proposal is made, the idea
> has received informal support in the past [1]_; both the introduction
> of finer-grained exception classes and the coalescing of OSError and
> IOError.
>
> The removal of WindowsError alone has been discussed and rejected
> as part of another PEP [2]_, but there seemed to be a consensus that the
> distinction with OSError wasn't meaningful.  This supports at least its
> aliasing with OSError.
>
>
> Moratorium
> ==========
>
> The moratorium in effect on language builtins means this PEP has little
> chance to be accepted for Python 3.2.
>
>
> Possible alternative
> ====================
>
> Pattern matching
> ----------------
>
> Another possibility would be to introduce an advanced pattern matching
> syntax when catching exceptions.  For example::
>
>    try:
>        os.remove(filename)
>    except OSError as e if e.errno == errno.ENOENT:
>        pass
>
> Several problems with this proposal:
>
> * it introduces new syntax, which is perceived by the author to be a
> heavier
>  change compared to reworking the exception hierarchy
> * it doesn't decrease typing effort significantly
> * it doesn't relieve the programmer from the burden of having to remember
>  errno mnemonics
>

ugh.  no.  :)  That only works well for single exceptions and encourages
less explicit exception types.  Exceptions are a class hierarchy, we should
encourage its use rather than encouraging magic type specific attributes
with conditionals.

-gps
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20100724/09608af8/attachment.html>


More information about the Python-ideas mailing list