在try-except块中使用python“ with”语句

问题:在try-except块中使用python“ with”语句

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

Is this the right way to use the python “with” statement in combination with a try-except block?:

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

If it is, then considering the old way of doing things:

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

Is the primary benefit of the “with” statement here that we can get rid of three lines of code? It doesn’t seem that compelling to me for this use case (though I understand that the “with” statement has other uses).

EDIT: Is the functionality of the above two blocks of code identical?

EDIT2: The first few answers talk generally about the benefits of using “with”, but those seem of marginal benefit here. We’ve all been (or should have been) explicitly calling f.close() for years. I suppose one benefit is that sloppy coders will benefit from using “with”.


回答 0

  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())

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

  1. The two code blocks you gave are not equivalent
  2. The code you described as old way of doing things has a serious bug: in case opening the file fails you will get a second exception in the finally clause because f is not bound.

The equivalent old style code would be:

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

As you can see, the with statement can make things less error prone. In newer versions of Python (2.7, 3.1), you can also combine multiple expressions in one with statement. For example:

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

Besides that, I personally regard it as bad habit to catch any exception as early as possible. This is not the purpose of exceptions. If the IO function that can fail is part of a more complicated operation, in most cases the IOError should abort the whole operation and so be handled at an outer level. Using with statements, you can get rid of all these try...finally statements at inner levels.


回答 1

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

是的,你结合的方式with,并try-except为几乎做到这一点的唯一方法,因为内造成特殊错误open本身不能内被捕获的语句with块。

If the contents of the finally block are determined by the properties of the file object being opened, why shouldn’t the implementer of the file object be the one to write the finally block? That’s the benefit of the with statement, much more than saving you three lines of code in this particular instance.

And yes, the way you’ve combined with and try-except is pretty much the only way to do it, as exceptional errors caused within the open statement itself can’t be caught within the with block.


回答 2

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

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

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

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

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

I think you got it wrong about “with” statement that it only reduces lines. It actually does initialization and handle teardown.

In your case “with” does

  • open a file,
  • process its contents, and
  • make sure to close it.

Here is link for understanding “with” statement : http://effbot.org/zone/python-with-statement.htm

Edit: Yes your usage of “with” is correct and functionality of both blocks of code is identical. Question about why to use “with” ? it’s because of benefits you get with it. like you mentioned about accidentally missing f.close().


回答 3

以下代码的更多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()

The more Pythonic way for the following codes is:

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()