使用带有try-except块的python“with”语句

Posted

技术标签:

【中文标题】使用带有try-except块的python“with”语句【英文标题】:Using python "with" statement with try-except block 【发布时间】:2011-04-08 05:03:36 【问题描述】:

这是将python“with”语句与try-except块结合使用的正确方法吗?:

try:
    with open("file", "r") as f:
        line = f.readline()
except IOError:
    <whatever>

如果是,那么考虑旧的做事方式:

try:
    f = open("file", "r")
    line = f.readline()
except IOError:
    <whatever>
finally:
    f.close()

这里的“with”语句的主要好处是我们可以摆脱三行代码吗? 这个用例对我来说似乎没有什么吸引力(尽管我知道“with”语句还有其他用途)。

编辑:以上两段代码的功能是否相同?

EDIT2:前几个答案一般都在谈论使用“with”的好处,但这些似乎是边际收益。多年来,我们都(或应该)明确地调用 f.close()。我想一个好处是马虎的编码员会从使用“with”中受益。

【问题讨论】:

Catching an exception while using a Python 'with' statement的可能重复 对我来说,不必记住在 finally 语句中关闭()的东西是使用 'with' 的充分理由。我已经看到很多代码无法关闭其资源。据我所知,“with”没有缺点。 【参考方案1】:
    您提供的两个代码块是 等效 您描述为旧方式的代码 of doing things有一个严重的bug: 万一打开文件失败 将在 finally 子句因为 f 不是 绑定。

等效的旧式代码是:

try:
    f = open("file", "r")
    try:
        line = f.readline()
    finally:
        f.close()
except IOError:
    <whatever>

如您所见,with 语句可以减少出错的可能性。在较新版本的 Python(2.7、3.1)中,您还可以在一个 with 语句中组合多个表达式。例如:

with open("input", "r") as inp, open("output", "w") as out:
    out.write(inp.read())

除此之外,我个人认为尽早捕获任何异常是一种坏习惯。这不是例外的目的。如果可能失败的 IO 函数是更复杂操作的一部分,则在大多数情况下 IOError 应该中止整个操作,因此在外部级别进行处理。使用with 语句,您可以在内部级别摆脱所有这些try...finally 语句。

【讨论】:

早点使用异常就好了。 Python 鼓励在许多情况下使用它们进行控制。【参考方案2】:

如果finally 块的内容是由正在打开的文件对象的属性决定的,为什么文件对象的实现者不应该是编写finally 块的人呢? 这就是with 语句的好处,远不止在这个特定实例中为您节省三行代码。

是的,您将withtry-except 组合在一起的方式几乎是唯一的方法,因为open 语句本身引起的异常错误无法在with 中捕获块。

【讨论】:

【参考方案3】:

我认为您对“with”声明的理解是错误的,它只会减少行数。 它实际上进行初始化并处理拆卸。

在你的情况下,“with”可以

打开一个文件, 处理其内容,并 确保关闭它。

这里是理解“with”语句的链接:http://effbot.org/zone/python-with-statement.htm

编辑:是的,您对“with”的使用是正确的,并且两个代码块的功能是相同的。 关于为什么使用“with”的问题?这是因为您从中获得的好处。就像您提到的意外丢失 f.close() 一样。

【讨论】:

【参考方案4】:

以下代码更 Pythonic 的方式是:

try:
    f = open("file", "r")
    try:
        line = f.readline()
    finally:
        f.close()
except IOError:
    <whatever>

try:
    f = open("file", "r")
except IOError:
    <whatever>
else:
    f.close()

【讨论】:

我为你添加了代码格式;它使阅读更容易。但您可能需要仔细检查以确保我没有破坏缩进。 不,您的版本与原始代码不一样。即使您添加缺少的readline() 调用,如果readline() 导致IOError,您的版本也不会关闭文件。

以上是关于使用带有try-except块的python“with”语句的主要内容,如果未能解决你的问题,请参考以下文章

python中常见错误及try-except 的用法

python 捕捉异常assert和try-except

无法在 try-except 结构中编译并返回 Python 函数

Python基础---异常

如何在 Python3 中使用带有 if __name__='__main__' 块的相对导入?

Python3基础 else 语句 与try-except配合