11

通常,当有人发布他们的代码时,人们会补充说“你with open('filename') as f现在应该使用语法”。我同意大多数老式f = open()语句都没有附带.close()的 ,我什至回答了对“隐式关闭”的依赖是他们编程问题的全部原因的问题。

但是,在某些情况下,将代码嵌套在with块中似乎会给编写代码带来其他不便。例如我有时喜欢在开头用一个标志来表示writefile = True。这让我只在要使用文件时打开和关闭文件,同时保持相同的处理线程。在代码的不同位置,我可以打印到屏幕或写入文件。(我意识到我会stdout在开头打开文件并使用该方法。)

我的问题是:除了不必显式关闭文件之外,还有其他理由使用with语法来处理文件,尤其是输出文件吗?(“更多pythonic”本身并不是一个原因。)如果这是重复的,我会很高兴指出这一点,但我自己找不到。

4

4 回答 4

10

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

无论如何,您都需要一个作用域块,以便在发生异常时关闭文件:

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

with因此,无论您如何编写代码,您所描述的缺点实际上都是正确代码的缺点(在需要清理的情况下)。

于 2013-10-31T16:13:24.173 回答
3

我们希望保证进行一些清理/完成。那就是使用with.

是的,最常见的是,我们想关闭一个文件,但您可以提出其他示例。

PEP 343有一个非文件示例:

用于确保在块开始时获取的锁在离开块时释放的模板:

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

使用如下:

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).
于 2013-10-31T16:13:18.540 回答
2

除了不必显式关闭文件之外,还有其他理由使用 with 语法来处理文件

我认为在文件打开期间使用的主要原因ContextManager是认为无论一切正常还是引发任何异常,该文件都将在任何情况下打开。

它是以下语句的模拟

f = open(filename, 'w')
try:
    pass
finally:
    f.close()
于 2013-10-31T16:09:58.673 回答
2

例如,我有时喜欢在开头使用一个标志来表示 writefile = True。这让我只在要使用文件时打开和关闭文件,同时保持相同的处理线程。在代码的不同位置,我可以打印到屏幕或写入文件。(我意识到我会在开始时打开标准输出或文件并使用该方法。)

这描述了具有大量重复 if 语句的代码。

除了不必显式关闭文件之外,还有其他理由使用 with 语法来处理文件,尤其是输出文件吗?

它消除了编写您自己的finally块的需要,并且它构造了您的代码以避免重复的 if 语句,并且它允许读者轻松找到定义文件对象(或者更确切地说是保存文件对象的变量)的位置。

因此,您可以这样做,而不是乱七八糟的标志:

with (open('file') if condition else io.BufferedWriter(sys.stdout)) as f:
     pass
于 2013-10-31T16:23:52.333 回答