为什么在Python中使用 `with open()` 打开文件更好?

14
经常有人发布他们的代码时,会附带一句话说“现在应该使用with open('filename') as f语法。”我同意大多数老式f = open()语句没有相应的.close(),我甚至回答过这种依赖“隐式关闭”导致编程问题的问题。
然而,在某些情况下,将代码嵌套在with块内似乎会在编写代码时产生其他不便之处。例如,我有时喜欢在开头使用一个标志writefile=True。这让我只有在需要使用文件时才打开和关闭文件,同时保持相同的处理线程。在代码中的各个地方,我可以将内容打印到屏幕或写入文件。(我意识到我会在开头打开stdout或文件,然后使用那种方法)。
我的问题是:除了不必显式关闭文件外,是否还有其他原因要使用with语法来处理文件,特别是输出文件?(仅仅因为“更符合Python风格”并不是一个原因。)如果这是一个重复的问题,我很乐意让别人指出来,但我自己找不到。

2
不,with 没有其他的好处。如果您的设计更适合使用 openclose 组合,那么请随意使用它。 - RickyA
1
谢谢大家。我非常感激你们的专业知识和见解。 - beroe
4个回答

11

使用with没有其他优点:它的唯一作用是确保清理。

无论如何,您都需要一个作用域块来在出现异常时关闭文件:

writefile = random.choice([True, False])
f = open(filename) if writefile else None
try:
    # some code or other
finally:
    if writefile:
        f.close()

所以,你所描述的with的劣势实际上是正确的代码的劣势(在需要清理的情况下),无论你如何编写。


3
我们希望确保进行一些清理/完成工作。这就是使用with的目的。
是的,通常情况下,我们希望关闭文件,但你也可以想出其他例子。 PEP 343提供了一个非文件示例:

A template for ensuring that a lock, acquired at the start of a block, is released when the block is left:

@contextmanager
def locked(lock):
    lock.acquire()
    try:
        yield
    finally:
        lock.release()

Used as follows:

with locked(myLock):
    # Code here executes with myLock held.  The lock is
    # guaranteed to be released when the block is left (even
    # if via return or by an uncaught exception).

2

除了不需要显式关闭文件之外,使用with语法处理文件的其他原因是什么?

我认为在打开文件时使用ContextManager的主要原因是,无论一切是否正常或任何异常是否被触发,该文件都将处于打开状态。

这类似于以下语句:

f = open(filename, 'w')
try:
    pass
finally:
    f.close()

2
例如,有时我喜欢在开头使用一个标志来表明writefile = True。这样可以让我只在需要使用时打开和关闭文件,同时保持相同的处理线程。在代码的各个地方,我可以选择向屏幕输出或写入文件。(我意识到我应该在开头打开stdout或文件并使用该方法。)
这描述了带有大量重复if语句的代码。
除了不必显式关闭文件之外,是否有其他原因要使用with语法处理文件,特别是输出文件?
它消除了编写自己的finally块的需要,并结构化代码,使您避免重复的if语句,并且它允许读者轻松找到定义文件对象(或变量持有文件对象的位置)的地方。
因此,您可以使用以下代码而不是混乱的标志:
with (open('file') if condition else io.BufferedWriter(sys.stdout)) as f:
     pass

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接