【问题标题】:how with open statement works when an exception occurs发生异常时 with open 语句如何工作
【发布时间】:2015-02-15 00:39:05
【问题描述】:

朋友们,

我试图用 try/except 块打开一个文件。

try:
    with open(finput[1], "r") as f:
        for line in f:
            if "NQ" in line[:2]:
                nq = int(line[-3:].strip())

except EnvironmentError:
    print(("Oops! File \"{:s}\" does not exist!").format(f))
#    print(("Oops! File \"{:s}\" does not exist!").format(finput[1]))
    sys.exit(0)

当我在 except 中使用 finput[1] 时(即现在已注释),它可以正常工作并按预期提供文件名。 但是如果我使用f(因为我试图将文件finput[1]打开为f),它会给我错误: 回溯(最近一次通话最后): 文件“readspr.py”,第 30 行,在 print(("糟糕!文件\"{:s}\"不存在!").format(f)) NameError: name 'f' is not defined

我在 python 方面没有多少经验(只知道编码,但不知道它是如何工作的。)。 所以,我对此的解释是: 因为,以f 打开文件失败,f 中没有存储任何内容;因此它是未定义的。

但是,另一方面,python 似乎会尝试以f 打开文件,因此,finput[1] 中的任何内容都作为变量字符串分配给f,python 无法打开文件f

我不确定这里是什么情况。我试图从互联网上的许多部分(即7.2.1 of thisthe accepted answer here 等)中理解它,但只是找到了我使用它的用途:simplifying exception handling

如果您能解释为什么不将f 视为例外,这将对我有所帮助。

【问题讨论】:

    标签: python-3.x


    【解决方案1】:

    问题实际上不是范围之一(请参阅Variable defined with with-statement available outside of with-block?)。问题是,如果open 内部发生异常,则永远不会执行as f 语句,因此尚未定义f。如果故障发生在with 块内,那么f 仍然是一个有效的引用。

    换句话说,这里的with 声明没有什么特别之处。您的特殊情况在语义上等同于尝试执行以下操作:

    try:
        f = open(filename)
    except EnvironmentError:
        # Trying to use f here is invalid, since it was never defined if open failed
    

    【讨论】:

    • 感谢您的回复。但是,我在完全得到这个方面有一个问题。当open 块没问题时,with 块是否会失败?
    • with EXP as VAR: 语法是language specification 的一部分,因此如果失败,这将是 Python 实现中的一个非常严重的错误。不确定这是否正是您要问的。如果您的意思是“可以在 with 语句 raise 的缩进范围内发生的代码”,那么当然,就像它可以在 python 程序中的其他任何地方一样。 f 在这种情况下仍然会被定义。
    • 更清楚地说,将open 包装在with 中的原因是,在退出with 语句的范围时会自动调用File.close(),无论是否达到该点,因为代码块成功完成或因为它引发了异常。 Context managers 用于确保资源不会泄漏/即使在抛出异常的情况下也始终被清理,这是它们的主要目的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 2010-10-17
    • 2012-03-06
    • 2015-05-17
    • 2014-05-08
    • 1970-01-01
    相关资源
    最近更新 更多