Python的"open()"抛出不同的“文件未找到”错误 - 如何处理这两种异常?

49 投票
4 回答
113828 浏览
提问于 2025-04-17 16:48

我有一个脚本,用户需要输入一个文件名(也就是要打开的文件名),如果当前目录下没有这个文件,用户会被要求再输入一次。下面是简化版的代码:

file = input("Type filename: ")

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

我在我的Mac电脑上用Python 3.3x测试这个脚本时,故意输入错误的文件名,它运行得非常顺利(会执行“expect”下的代码)。

但是,当我想在Windows电脑上用Python 3.2x运行我的代码时,出现了一个错误,提示“FileNotFoundError”没有定义。所以,Windows上的Python 3.2把“FileNotFoundError”当成了一个变量,结果程序就出错退出了。

我发现Windows上的Python 3.2如果输入的文件名不合法,会抛出一个“IOError”。我在我的Linux机器上用Python 2.7测试,也是抛出IOError。

现在我的问题是,下面这段代码

except "FileNotFoundError":

在Windows的Python 3.2上无法运行,但如果我把它改成

except "IOError":

就不能在我的Mac上运行了。

我该怎么解决这个问题呢?我能想到的唯一方法就是只用 except,但我通常不想这样做。

4 个回答

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
9

我觉得这个方法比简单的 except: 要好,但我不确定这是否是最好的解决方案:

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

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

在3.3版本中,IOError变成了OSError的一个别名,而FileNotFoundErrorOSError的一个子类。所以你可以尝试下面的代码:

except (OSError, IOError) as e:
   ...

这样做会捕捉到很多不同的错误,你不能仅仅通过检查e.errno来假设这个错误就是“文件未找到”,但这可能适合你的使用场景。

PEP 3151详细讨论了这个变化的原因。

撰写回答