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

时间:2010-09-04 11:35:29

标签: python finally with-statement try-catch except

这是将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”中受益。

4 个答案:

答案 0 :(得分:124)

  1. 您提供的两个代码块是 等效
  2. 您描述为旧方式的代码 做事有一个严重的错误: 万一打开文件失败了 将获得第二个例外 finally条款,因为f不是 界。
  3. 等效的旧样式代码是:

    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语句。

答案 1 :(得分:6)

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

是的,你将withtry-except结合起来的方式几乎是唯一的方法,因为open语句本身导致的异常错误不可能是陷入with区块。

答案 2 :(得分:1)

我认为你对“with”声明说错了它只会减少行数。 它实际上做了初始化和处理拆解。

在你的情况下,“with”确实

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

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

编辑:是的,你对“with”的使用是正确的,两个代码块的功能是相同的。 关于为何使用“with”的问题?这是因为你得到的好处。就像你提到的意外丢失了f.close()。

答案 3 :(得分:-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()