josch
josch

Reputation: 7174

List of exceptions for Python3 I/O operations for proper error handling

I'm trying to write to a file like this:

with open(filename), 'wb') as f:
    f.write(data)

But when opening a file and writing to it many things might go wrong and I want to properly report what went wrong to the user. So I don't want to do:

try:
    with open(filename), 'wb') as f:
        f.write(data)
except:
    print("something went wrong")

But instead I want to tell the user more specifics so that they can fix the problem on their end. So I started with catching the PermissionError to tell the user to fix their permissions. But soon I got a bugreport that the program would fail if filename pointed to a directory, so I also caught and reported the IsADirectoryError. But this is not all - it might be that the path to filename doesn't exist, so later I also added the FileNotFoundError.

Opening a file and writing to it is a very simple pattern but still many things can go wrong. I'm wondering whether there is an easy recipe that allows me to catch these errors and report them properly without giving a generic "some error happened" message. This kind of pattern has been used for decades, so there must be some list of things to check for, no?

I now caught a number of exceptions but I can imagine that even more are lurking around. Things probably become even worse when running this on non-Linux platforms...

What are the best practices for opening a file and writing to it in Python that give a maximum of information back to the user when things go wrong without ressorting to dumping the bare traceback?

On the operating system level there are only so many things that can go wrong when doing an open() and write() system call so there must exist a complete list?

Upvotes: 4

Views: 1075

Answers (1)

mhawke
mhawke

Reputation: 87134

You could catch the higher level exception OSError and then present the value of the strerror field to the user as the explanation. This relies on the fact that exceptions such as FileNotFoundError are subclasses of OSError and these subclasses can all be caught by using the base class.

Here's an example:

try:
    filename = 'missing_file'
    with open(filename) as f:
        for line in f:
            # whatever....
            pass
except OSError as exc:
    print('{!r}: {}'.format(filename, exc.strerror))

Running this code when missing_file does not exist produces this error message:

'missing_file': No such file or directory

Upvotes: 4

Related Questions