一次性读取整个文件是否需要使用with语句?

4

我使用它已经有12年了:

content=open(foo).read()

新来的大学同事说:你应该使用 with 语句。

with open(foo) as fd:
    content=fd.read()

我认为我没必要多打字,除非有充分的理由需要这么做。
使用with语句的唯一好处是,在块结束时会自动关闭文件描述符fd。如果不使用with语句,当垃圾回收机制开始工作时才会关闭文件描述符fd
请告诉我:如果我一次读取整个文件,为什么还需要使用with语句?
更新:我知道with语句的工作原理,也知道它的用途(例如写入文件)。

1
http://effbot.org/zone/python-with-statement.htm 是一个有用的解释它的作用。 - Paul Tomblin
1
@duffymo "现在需要它" - 这是一个明显错误的说法... - Jon Clements
请注意,不同的Python实现对垃圾回收的细节是不同的。您只使用CPython吗? - wim
5个回答

4

对于您的目的来说,实际上没有真正的理由。然而,with的用处不仅限于文件。它可以与线程一起使用。例如:

import threading
lock = threading.Lock()
with lock:
    # Critical section
    statements
    # End critical section
with语句在进入和离开其后面的语句块时自动获取并释放锁。
使用with语句已成为良好的编程实践,因为它可以增加代码的安全性,并使文件读取部分更加突出和易于阅读(在我看来),因为当您使用with语句时,实际上是在缩进块内部。

1
值得注意的是,在您的示例中实现了您提到的逻辑的是“lock”对象。 “with”关键字只是触发它。 - Paolo Casciello
1
我认为这不是一个令人信服的论点。OP问为什么在这个例子中应该使用with,而不是它在一般情况下的好处。类比一下:+运算符用于累加数字很有用,但这并不意味着它应该用于累加字符串。 - user395760
@guettli 没错,实际上对于你的目的来说并没有什么太大的作用。这基本上就是每个人都在说的。这只是最佳实践。 - Games Brainiac

1
原因很明显:上下文管理器在离开上下文管理器块后关闭打开的文件。使用上下文管理器可以提供额外的安全性。
例如,我有以下代码:
content = open('foo.txt').read()
os.unlink('foo.txt')

这段代码在Linux上运行得非常好,但是在Windows上出现了问题,因为文件仍然保持打开状态,导致Windows抛出异常(据我记得可能是文件被锁定之类的)。
如果将代码编写为:这种错误就不会发生。
with open('foo.txt') as fp:
    content= fp.read()
os.unlink('foo.txt')

读取文件内容后,在尝试unlink()删除文件之前,文件将被关闭。

这并没有回答问题。OP问为什么在其示例中使用with比使用单行代码更好。 - Paolo Casciello
1
这是一个很好的理由。在Windows上,这个一行代码不起作用。我从不使用Windows,但无论如何,这是一个很好的观点。 - guettli

1

关闭未使用的句柄而不是等待GC是一个好的实践。

顺便说一下,你的观点是正确的,在你的情况下使用with没有明显的好处。 并且由于使用with进行显式关闭,可能会有不到一毫秒的惩罚。


0

一次性读取整个文件对关闭文件没有影响。不管你对文件做什么(除非显式地关闭它),没有使用 with 语句,文件将一直保持打开状态,直到调用其 __del__ 方法。因此,使用 with 的原因适用于文件 I/O 的每个使用情况,包括你的使用情况:

它确实尽早地关闭文件。它不受引用循环的影响,对其他 Python 实现更具可移植性(想象一下,如果你可以从 PyPy 获得 5 倍的性能提升,但由于打开了太多的文件而导致程序崩溃,你不能使用它!)。即使在当前上下文中并不重要,代码也可能被移动和要求改变。这是一种轻松的方式(只需添加一行额外代码!)来未来证明代码的正确性。

如果它是一个每次运行只会打开两个文件的一次性脚本,使用 with 语句,仍然是良好的编程习惯和风格。就像你在一次性脚本中不能将缩进更改为五个空格的原因一样。


-3

使用with语句更好,因为它可以确保即使出现异常,文件也会被关闭。


3
这并没有回答这个问题。 - Games Brainiac

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