[Python-Dev] Comments of the PEP 3151

Nick Coghlan ncoghlan at gmail.com
Mon Jul 25 07:28:47 CEST 2011


On Mon, Jul 25, 2011 at 9:56 AM, Victor Stinner
<victor.stinner at haypocalc.com> wrote:
> By the way, is it faster to not handle and than re-raise unwanted
> exceptions?

Yes, but probably not that much faster given the overhead of
instantiating the exception and unwinding the stack in the first
place.

> Choice of the specific errors
> -----------------------------
>
> I don't understand how Antoine decided which errno should have an
> exception or not.
>
> For example, EINTR and EPIPE are handled in many modules of the standard
> library but don't have their exception, whereas EISDIR
> (IsADirectoryError) and ENOTDIR (NotADirectoryError) are very rare
> (EISDIR is never handled in the standard library) but have their
> exception.

We do tend to call isdir() fairly often, though. Part of the appeal of
isdir() is the ugliness of using EAFP when you have to do explicit
errno checks.

> If we add EINTR, I don't know if it's better to add it to
> BlockingIOError or to create a new exception (InterruptError?).

InterruptedError seems like a reasonable candidate for addition to me
- catch and retry in that case is something developers are likely to
want to do.

Perhaps EPIPE should map to FileDescriptorError along with EBADF, with
different messages based on the exact error code? Potentially renamed
to DescriptorStateError? I'm not sure of the reason for singling out
EBADF for special treatment in this case - there are several other
errno values that indicate a descriptor is no longer in a usable state
(ECONSHUTDOWN would be another one, in the same vein as EPIPE).

To be honest though, what's the use case for *catching*
FileDescriptorError without catching IOError in general? Perhaps this
one should be dropped entirely, to be handled by broadly catching
IOError?

> Another good candidate is EINVAL.

As with EBADF, I'm having trouble visualising a clear use case for
handling things like EINVAL and EOPNOTSUP differently from other kinds
of IO errors.

> Would it be possible to have an (exhaustive?) list of errno with their
> popularity? At least, their popularity in the Python standard library?

Probably, but the stdlib is more a *generator* of low level
exceptions, so our code likely isn't representative enough to get a
decent set of numbers.

> If we provide an error message error: should it be localized? The
> description of FileDescriptorError tells about the "default error
> message". It we use a localized message, it's not possible to
> preallocate or cache instances.

We don't localize anything else, so there's no reason to start here.

> PermissionError
> ---------------
>
> EACCES and EPERM have a different meaning. Even that they are very
> similar, we might provide two different exceptions. EPERM is only used
> once in the Python stdlib, so we might only provide AccesError.
>
> On Linux, EPERM usually indicates an operation requiring root
> priviledge.  EACCES can be related to filesystem permissions (read-only,
> user is not allowed to write, etc.) or can be an mmap error.

Code that cares can still fall back to exc.errno == EPERM. I don't
think we'd be doing anyone any favours by exposing subtle distinctions
like this at the Python level.

> Deprecation
> -----------
>
> Because IOError, OSError, select.error, etc. are well known exceptions,
> I'm not in favor of removing them from Python 3. It would make porting
> from Python 2 worse. If we don't remove them, they should not be
> deprecated.
>
> I'm in favor of adding a note in the documentation of all legacy
> exceptions to advice to use IOError or specific exceptions instead. I
> suppose that these notes will have to indicate a Python version.

+1 for grandfathering in the old exception names, but documenting the
recommended alternatives as of 3.3.

> -1 on FileSystemError
> ---------------------
>
> I'm not sure that we need FileSystemError or ConnectionError. Careless
> code will use IOError, whereas careful code will use an explicit list
> like (ConnectionAbortedError, ConnectionRefusedError,
> ConnectionResetError).
>
> If we remove IsADirectoryError and NotADirectoryError, FileSystemError
> only contains FileExistsError and FileNotFoundError. I don't think that
> these errors can occur on a same function. For example, rmdir() only
> raises ENOTDIR.
>
> I only see one advantage of FileSystemError: it doesn't handle
> FileDescriptorError. Advice usage of FileSystemError would avoid to hide
> real bugs like FileDescriptorError.

And that's precisely why FileSystemError is worthwhile - to separate
out when the FS is objecting, rather than there being something wrong
with the internal application state or when a previously valid
descriptor has become unusable for some reason.

It may also be reasonable to return a new DeviceNotAvailableError for
ENODEV and EBUSY (as a new FileSystemError subclass).

> I don't really care of ConnectionError. Anyway, FileSystemError and
> ConnectionError can be added later if needed.

But the use case for grouping them is quite obvious - there's is
plenty of application code that will want to handle them in a
particular way, while allowing other kinds of IOError to propagate
further up the stack. Baking this into the exception heirarchy is far
more future proof than people making their own explicit lists.

There may be some error codes that we choose to map to these generic
errors, even if we don't give them their own exception types at this
point (e.g. ECONSHUTDOWN could map directly to ConnectionError).

> Should FileNotFound handle ENODEV? (see test_ossaudiodev)

See above for my suggestion of a specific DeviceNotAvailable exception.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia


More information about the Python-Dev mailing list