在try-except块中使用python的"with"语句

122 投票
4 回答
111864 浏览
提问于 2025-04-16 03:42

这是使用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”语句还有其他用法)。

编辑:上面这两个代码块的功能是一样的吗?

编辑2:前面的一些回答一般性地谈到了使用“with”的好处,但在这里似乎帮助不大。我们都已经(或者应该已经)显式地调用f.close()很多年了。我想一个好处是,写代码不太认真的人会从使用“with”中受益。

4 个回答

0

我觉得你对“with”语句的理解有点偏差,它并不仅仅是为了减少代码行数。

实际上,它还负责初始化和处理清理工作。

在你的例子中,“with”做了以下几件事:

  • 打开一个文件,
  • 处理文件的内容,
  • 确保最后关闭这个文件。

这里有一个链接可以帮助你理解“with”语句: http://effbot.org/zone/python-with-statement.htm

补充一下:是的,你使用“with”的方式是正确的,两个代码块的功能是一样的。

关于为什么要使用“with”的问题?这是因为它带来的好处,比如你提到的可能会忘记写 f.close() 的情况。

8

如果finally块里的内容是根据正在打开的文件对象的属性来决定的,那为什么不让文件对象的实现者来写这个finally块呢?这就是使用with语句的好处,远不止是在这个特定情况下节省三行代码。

而且,是的,你把withtry-except结合起来的方式几乎是唯一的做法,因为在open语句本身引发的异常错误是无法在with块内捕获的。

158
  1. 你给的两个代码块并不相同
  2. 你说的那种老方法有个严重的错误:如果打开文件失败,你会在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函数是更复杂操作的一部分,在大多数情况下,IO错误应该终止整个操作,因此应该在外层处理。使用with语句,你可以摆脱所有这些内层的try...finally语句。

撰写回答