Python的“open()”对于“文件未找到”会抛出不同的错误——如何处理这两个异常?

49

我有一个脚本,用户需要输入文件名(要打开的文件),如果该文件不存在于当前目录中,则会提示用户重新输入。以下是简短版本:

file = input("Type filename: ")

...
try:
    fileContent = open(filename, "r")
    ...
except FileNotFoundError:
    ...

当我在我的MacOS X上使用Python 3.3x测试脚本时,如果我故意输入错误的文件名(它会在“expect”下执行),它能够完美地运行。

然而,当我想在Windows计算机上使用Python 3.2x运行我的代码时,我会收到一个错误,说"FileNotFoundError"未定义。因此,Windows上的Python 3.2认为"FileNotFoundError"是一个变量,并且程序以错误退出。

我发现,在Windows上,如果输入的文件名无效,Python 3.2会抛出"I/O错误"。我在我的Linux机器上使用Python 2.7进行了测试,也是一个I/O错误。

我的问题是,带有

的代码在Windows上无法正常工作,但在其他操作系统上可以正常工作。
except "FileNotFoundError":

无法在Windows上的Python 3.2上运行,但如果我将其更改为
except "IOError":

我的Mac上不能再运行它了。

我该怎么解决?我能想到的唯一方法是仅使用except,但通常我不想这样做。


7
这不是由于Mac/Windows,而是由于Python的版本。我建议在OS X上调查3.2/3.3版本(以及Windows上的3.3版本),查阅更改日志,然后根据需要修改问题/标题。 - user166390
4个回答

78
在3.3版本中,IOError成为OSError的别名, 而FileNotFoundErrorOSError的子类。因此你可以尝试
except (OSError, IOError) as e:
   ...

这将覆盖很广泛的情况,你不能假设异常是“文件未找到”,必须检查e.errno,但它可能符合你的用例。 PEP 3151详细讨论了更改的原因。

同时捕获PermissionError - 用于捕获所有错误信息 - print('Error:', e.args[1]) - Stuart Cardall

9

我认为这比简单的 except: 更好,但我不确定它是否是最佳解决方案:

error_to_catch = getattr(__builtins__,'FileNotFoundError', IOError)

try:
    f = open('.....')
except error_to_catch:
    print('!')

在其他新闻中,except: 后面跟着一个逗号在语法上是正确的,但仍然显得非常奇怪。 - cwallenpoole
这也是一个非常好的解决方案。比 except(IOError, OSError): 稍微长一点,但更加具体。 - user2015601
这是一个反模式。 - omni

7

因此,为了确切地捕捉文件未找到的情况,我会这样写:

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

2
您可以同时捕获2个错误 except (FileNotFoundError, IOError): 我没有意识到这就是您所要求的。希望有更优雅的解决方案,而不是手动检查。
try:
   error_to_catch = FileNotFoundError
except NameError:
   error_to_catch = IOError

except error_to_catch

cwallenpoole在他的回答中以更加优雅的方式使用了此条件语句 (error_to_catch = getattr(__builtins__,'FileNotFoundError', IOError))


2
这会管用吗——我得到一个错误,说“FileNotFoundError”未定义。所以,在Windows上的Python 3.2中,“FileNotFoundError”被认为是一个变量,程序因此退出并出现错误 - user166390
@pst 有趣,抱歉没有考虑到它。 - dm03514

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接