[Python-Dev] Comments of the PEP 3151 (original) (raw)

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

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 testossaudiodev)

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