What is a good way to handle exceptions when trying to read a file in python?
Solution 1
How about this:
try:
f = open(fname, 'rb')
except OSError:
print "Could not open/read file:", fname
sys.exit()
with f:
reader = csv.reader(f)
for row in reader:
pass #do stuff here
Solution 2
Here is a read/write example. The with statements insure the close() statement will be called by the file object regardless of whether an exception is thrown. http://effbot.org/zone/python-with-statement.htm
import sys
fIn = 'symbolsIn.csv'
fOut = 'symbolsOut.csv'
try:
with open(fIn, 'r') as f:
file_content = f.read()
print "read file " + fIn
if not file_content:
print "no data in file " + fIn
file_content = "name,phone,address\n"
with open(fOut, 'w') as dest:
dest.write(file_content)
print "wrote file " + fOut
except IOError as e:
print "I/O error({0}): {1}".format(e.errno, e.strerror)
except: #handle other exceptions such as attribute errors
print "Unexpected error:", sys.exc_info()[0]
print "done"
Solution 3
How about adding an "else" clause to the exception and putting the "with" statement in the "else" section? Like this:
try:
f = open(fname, 'rb')
except FileNotFoundError:
print(f"File {fname} not found. Aborting")
sys.exit(1)
except OSError:
print(f"OS error occurred trying to open {fname}")
sys.exit(1)
except Exception as err:
print(f"Unexpected error opening {fname} is",repr(err))
sys.exit(1) # or replace this with "raise" ?
else:
with f:
reader = csv.reader(f)
for row in reader:
pass #do stuff here
Instead of sys.exit(), you could put 'raise' and escalate the error up the chain. It might be better to get system info about the error from the top level error handler.
Solution 4
I updated Tim Pietzcker answer, because it uses Python 2 which is not maintained anymore.
I tried to edit the answer first, but I got: edit queue is full, so I could not.
import errno
fname = "no_such_a_file.txt"
try:
f = open(fname, 'rb')
except OSError as e:
if e.errno == errno.ENOENT:
print(
f"No such a file or directory (errno: { e.errno }):",
fname, file=sys.stderr
)
else:
# for other OS errno codes you may want to write
# your more specific error messages which
print(
f"Cannot oppen file (errno: { e.errno } ):",
fname,
file=sys.stderr
)
sys.exit(os.EX_OSFILE)
with f:
reader = csv.reader(f)
for row in reader:
pass #do stuff here
I also made some minor improvements:
The code is self-contained.
You should check the errno number of your exception, which helps you narrow down the error
You should write error and log messages into sys.stderr
and not into sys.stdout
(default for print), because then you can redirect your error messages into a different file.
You should return a non-zero exit code (documented here) which is a must if you want to make your python code usable in a Unix environment, such as a shell script:
#!/usr/bin/env bash
set -euo pipefail
if ./read_file.py 2> error.log
then
echo "do stuff"
else
exit_code=$?
echo "file is not readable, exit code: $exit_code" > /dev/stderr
exit $exit_code
fi
Solution 5
fname = 'filenotfound.txt'
try:
f = open(fname, 'rb')
except FileNotFoundError:
print("file {} does not exist".format(fname))
file filenotfound.txt does not exist
exception FileNotFoundError Raised when a file or directory is requested but doesn’t exist. Corresponds to errno ENOENT.
https://docs.python.org/3/library/exceptions.html
This exception does not exist in Python 2.
Related videos on Youtube
Charles Holbrow
Updated on July 08, 2022Comments
-
Charles Holbrow over 1 year
I want to read a .csv file in python.
- I don't know if the file exists.
- My current solution is below. It feels sloppy to me because the two separate exception tests are awkwardly juxtaposed.
Is there a prettier way to do it?
import csv fName = "aFile.csv" try: with open(fName, 'rb') as f: reader = csv.reader(f) for row in reader: pass #do stuff here except IOError: print "Could not read file:", fName
-
Rick over 6 yearsThe answers to this question should probably be updated to include usage of the
pathlib
module, which makes this problem a lot easier, and should probably be standard Python practice (especially since it was also backported to 2.7).
-
intuited almost 13 yearsThe only problem with this is that the file is opened outside of the
with
block. So if an exception occurs between thetry
block containing the call toopen
and thewith
statement, the file doesn't get closed. In this case, where things are very simple, it's not an obvious issue, but it could still pose a danger when refactoring or otherwise modifying the code. That being said, I don't think there's a better way to do this (other than the original version). -
jscs almost 13 years@intuited: That's right. In fact, the final answer to the OP is probably just: No, the way you've done it is the right way.
-
hotohoto over 4 years
FileNotFoundError.mro()
is[<class 'FileNotFoundError'>, <class 'OSError'>, <class 'Exception'>, <class 'BaseException'>, <class 'object'>]
andIOError.mro()
is[<class 'OSError'>, <class 'Exception'>, <class 'BaseException'>, <class 'object'>]
. How about using eitherOSError
orException
instead? ``` -
Tim Pietzcker over 4 years@hotohoto: Good idea. I'm not sure - perhaps the Exception hierarchy has changed in this regard since 2011, but anyway your suggestion is more encompassing.
-
Donald Duck almost 4 yearsWhile this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.
-
Mian Asbat Ahmad about 3 yearsIn this case, IOError is obvious but when will general exception occur from code coverage point of view. How can I make a test case to generate a general exception.
-
Ben Slade almost 3 yearsHow about making the "with f:" part of an "else:" clause for the exception? The spoken english version of this would be, "try and open, if error raise error, else do normal processing" Block code samples aren't allowed in comments, so I can't show it.
-
atevm over 2 yearsHi I tried to update your answer, but I got an edit queue is full error. So I had to write a new one. stackoverflow.com/a/68175784/1638350
-
Karthik Kumar over 2 yearsThis is indeed good way, in exception the program itself terminated.. then not to worry on further whats done. however if you are not exiting, then normal way how the question is asked itself can be the best.