Reputation: 7174
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
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