Python's "open()" throws different errors for "file not found" - how to handle both exceptions?
I have a script where a user is prompted to type a filename (of a file that is to be opened), and if the file doesn't exist in the current directory, the user is prompted again. Here is the short version:
file = input("Type filename: ")
...
try:
fileContent = open(filename, "r")
...
except FileNotFoundError:
...
When I tested my script on my MacOS X in Python 3.3x it worked perfectly fine when I type the wrong filename on purpose (it executes the suite under "expect").
However, when I wanted to run my code on a Windows computer in Python 3.2x, I get an error that says that "FileNotFoundError" is not defined. So, Python 3.2 on Windows thinks "FileNotFoundError" is a variable and the programs quits with an error.
I figured out that Python 3.2 on Windows throws an "IOError" if the input filename is not valid. I tested it on my Linux machine in Python 2.7, and it's also an IOError.
My problem is now, that the code with
except "FileNotFoundError":
won't run on Windows's Python 3.2, but if I change it to
except "IOError":
it won't work on my Mac anymore.
How could I work around it? The only way I can think of is to use just
except
, which I usually don't want.
In 3.3, IOError
became an alias for OSError
, and FileNotFoundError
is a subclass of OSError
. So you might try
except (OSError, IOError) as e:
...
This will cast a pretty wide net, and you can't assume that the exception is "file not found" without inspecting e.errno
, but it may cover your use case.
PEP 3151 discusses the rationale for the change in detail.
This strikes me as better than a simple except:
, but I'm not sure if it is the best solution:
error_to_catch = getattr(__builtins__,'FileNotFoundError', IOError)
try:
f = open('.....')
except error_to_catch:
print('!')
So to exactly catch only when a file is not found, I do:
import errno
try:
open(filename, 'r')
except (OSError, IOError) as e: # FileNotFoundError does not exist on Python < 3.3
if getattr(e, 'errno', 0) == errno.ENOENT:
... # file not found
raise