在尝试读取 python 中的文件时,处理异常的好方法是什么?

我想在 python 中读取一个.csv 文件。

  • 我不知道文件是否存在。
  • 我当前的解决方案如下所示。我感觉很草率,因为两个独立的异常测试并列在一起很尴尬。

还有比这更漂亮的方法吗?

import csv
fName = "aFile.csv"


try:
with open(fName, 'r') as f:
reader = csv.reader(f)
for row in reader:
pass #do stuff here
    

except IOError:
print "Could not read file:", fName
294459 次浏览

这样吧:

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

加上@Josh 的例子;

fName = [FILE TO OPEN]
if os.path.exists(fName):
with open(fName, 'rb') as f:
#add you code to handle the file contents here.
elif IOError:
print "Unable to open file: "+str(fName)

这样,您可以尝试打开该文件,但如果它不存在(如果它引发 IOError) ,请提醒用户!

下面是一个读/写示例。With 语句确保 close ()语句将由 file 对象调用,而不管是否引发异常。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"
fname = 'filenotfound.txt'
try:
f = open(fname, 'rb')
except FileNotFoundError:
print("file {} does not exist".format(fname))


file filenotfound.txt does not exist

异常 FileNotFoundError 当请求文件或目录但不存在时引发。对应于 errno ENOENT。

Https://docs.python.org/3/library/exceptions.html
这个异常在 Python2中不存在。

为异常添加一个“ else”子句,并将“ with”语句放在“ else”部分如何?像这样:

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

与 sys.exit ()不同,您可以使用‘ rose’并将错误向上升级。最好从顶级错误处理程序获取有关错误的系统信息。

我更新了 Tim Pietzcker 的答案,因为它使用了不再维护的 Python2。

我试图先编辑答案,但我得到: 编辑队列已满,所以我不能。

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


我还做了一些小小的改进:

代码是独立的。

您应该检查异常的 没错编号,这有助于缩小错误范围

您应该将错误消息写入 sys.stderr而不是 sys.stdout(打印时默认) ,因为这样可以将错误消息重定向到另一个文件。

你应该返回一个 非零出口代码(记录在案) ,如果你想让你的 python 代码在 Unix 环境中可用,这是必须的,比如一个 shell 脚本:

#!/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

在 Python3中,IOError 是 OSERror 的别名:

IOError is OSError
---
True

OSERror 是文件 I/O 异常的父类。

      +-- OSError
|    +-- BlockingIOError
|    +-- ChildProcessError
|    +-- ConnectionError
|    |    +-- BrokenPipeError
|    |    +-- ConnectionAbortedError
|    |    +-- ConnectionRefusedError
|    |    +-- ConnectionResetError
|    +-- FileExistsError
|    +-- FileNotFoundError
|    +-- InterruptedError
|    +-- IsADirectoryError
|    +-- NotADirectoryError
|    +-- PermissionError
|    +-- ProcessLookupError
|    +-- TimeoutError
OSError.__subclasses__()
---
[ConnectionError,
BlockingIOError,
ChildProcessError,
FileExistsError,
FileNotFoundError,
IsADirectoryError,
NotADirectoryError,
InterruptedError,
PermissionError,
ProcessLookupError,
TimeoutError,
io.UnsupportedOperation,
signal.ItimerError,
socket.herror,
socket.gaierror,
socket.timeout,
ssl.SSLError,
shutil.Error,
shutil.SpecialFileError,
shutil.ExecError,
shutil.ReadError,
urllib.error.URLError,
gzip.BadGzipFile]

因此,如果需要详细信息,请捕获 OSERror 并检查确切的类。

try:
with open('hoge') as f:
pass
except OSError as e:
print(f"{type(e)}: {e}")
---
<class 'FileNotFoundError'>: [Errno 2] No such file or directory: 'hoge'