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


84

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

  • 我不知道该文件是否存在。
  • 我当前的解决方案如下。我觉得草率,因为两个单独的异常测试并列在一起。

有更漂亮的方法吗?

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

如果不存在的文件不是错误的情况,而是可能的情况,则在可能的情况之前(以及除此之外)明确地检查并处理其不存在/不可读取性try。可以分别使用os.path.exists(file)os.access(file, os.R_OK)完成。尽管这种检查永远不可能摆脱比赛条件,但是消失的文件很少是正常情况;)
stefanct

2
这个问题的答案可能应该更新为包含pathlib模块的用法,这使此问题变得容易得多,并且应该是标准的Python惯例(尤其是因为它也已反向移植到2.7)。
里克(Rick)

在捕获时IOErrorcsv.Error由于文件不是CSV格式,Dialect.strict=True或者Error由于其他任何错误(根据CSV软件包文档)而无法捕获,因此外部尝试或仅检查文件是否存在,然后内部尝试CSV异常可能是正确的答案。
pink spikyhairman

@pinkspikyhairman是的,在您的except处理程序中,您必须确定要处理的错误类型。看到这里如何处理多种特定类型的错误:stackoverflow.com/questions/6470428/...
查尔斯Holbrow

Answers:


50

我想我误会了所要问的内容。重新阅读,看来蒂姆的答案就是你想要的。但是,让我添加一下:如果要从中捕获异常open,则open必须将其包装在中try。如果对的调用open位于的标头中with,则with必须在的标头中try以捕获异常。没有办法解决。

因此答案是:“提姆的方式”或“不,您做得正确”。


先前所有评论所指的无用答案:

import os

if os.path.exists(fName):
   with open(fName, 'rb') as f:
       try:
           # do stuff
       except : # whatever reader errors you care about
           # handle error


21
仅仅因为文件存在并不意味着您可以读取它!
加布

3
这不是完美的,因为在检查文件存在和尝试将其打开之间可能会删除该文件(例如,通过其他进程删除)。
Liquid_Fire 2011年

也许我误会了这个问题。实际上,我认为我绝对是。
jscs 2011年

1
也有fName可能是某个文件的名称,即使它粘在某个文件中,也无论出于何种原因都无法打开它-例如,如果它是目录或没有权限允许执行过程读取该文件。
直觉

4
“如果存在(文件):打开(文件)”方法可能会失败,因为可以在检查文件是否存在之后但在打开文件之前将其删除。或者它可能被锁定,或者没有读取权限,或者是某种您无法读取的对象(例如目录),或者被归档在磁带上而磁带不可用,或者可能是磁盘错误试图打开文件,或者...
Gabe

62

这个怎么样:

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

10
唯一的问题是文件是在with块外部打开的。因此,如果在try包含到的调用的块open与该with语句之间发生异常,则不会关闭文件。在这种情况下,事情非常简单,这不是一个明显的问题,但是在重构或修改代码时仍然可能构成危险。话虽这么说,但我认为没有更好的方法(原始版本除外)。
直觉

2
@intuited:是的。实际上,对OP的最终答案可能只是:不,您的操作方式是正确的方法。
jscs 2011年

1
FileNotFoundError.mro()[<class 'FileNotFoundError'>, <class 'OSError'>, <class 'Exception'>, <class 'BaseException'>, <class 'object'>]并且IOError.mro()[<class 'OSError'>, <class 'Exception'>, <class 'BaseException'>, <class 'object'>]。如何使用OSErrorException替代?```
hotohoto

1
@hotohoto:好主意。我不确定-也许自2011年以来Exception层次结构在这方面已经发生了变化,但是无论如何,您的建议都具有广泛性。
蒂姆·皮茨克

16

这是一个读/写示例。with语句可确保无论对象是否引发异常,文件对象都将调用close()语句。 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"

0
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在请求文件或目录但不存在时引发。对应于errno ENOENT。

https://docs.python.org/3/library/exceptions.html
此异常在Python 2中不存在。


1
尽管此代码可以回答问题,但提供有关如何和/或为什么解决问题的其他上下文将提高​​答案的长期价值。
唐老鸭

-11

添加到@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),请警告用户!


没有看到问题。如果语法不正确,则在执行时会引发语法错误!
扎克·布朗

7
不是语法错误,而是bool(IOError)简单Trueif不会捕获任何异常。

8
>>> if IOError: print "That's not an exception handler"
jscs 2011年

3
@Josh Caswell是正确的。IOError评估为True。docs.python.org/2.4/lib/truth.html
hecvd
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.