在Python中,通常建议使用with语句,或者在我们完成清理时关闭打开的文件。我知道当使用with时,会调用__enter__()和__exit__()方法。但是,如果我没有从数据流创建变量,该怎么办?就像这样:
with
__enter__()
__exit__()
import json def read_json(file): return json.load(open(file))
这会自动关闭文件吗?还有,有没有办法测试一下?谢谢。
xqkwcwgp1#
它会自动关闭吗?是的。退出作用域后,引用计数递减,文件描述符关闭。(但是不要试图在Jython中逃避这一点!)如何验证?咨询os.listdir('/proc/self/fd/')
os.listdir('/proc/self/fd/')
u5rb5r592#
在open()的特定情况下,即使您没有将其分配给变量,文件仍然是打开的,并且需要关闭以避免泄漏文件描述符。该文件从open()返回的那一刻开始打开,而不是在调用__enter__()时打开。(__enter__()实际上是内置文件类型的无操作,尽管并非所有上下文管理器都是如此。你可以通过跟踪Python创建的系统调用来看到这一点:
open()
$ strace python3 -c "open('test')" [...] openat(AT_FDCWD, "test", O_RDONLY|O_CLOEXEC) = 3
即使没有对变量赋值,也没有使用上下文管理器,仍然调用了openat()系统调用。在同一个跟踪中,我们可以看到close()系统调用也在之后被调用:
openat()
close()
close(3) = 0
这是因为文件描述符没有对它的引用,这会调用垃圾收集器,如果文件句柄没有显式关闭,垃圾收集器也会关闭文件句柄。然而,依赖CPython的这个实现细节通常被认为是不好的做法。我建议你明确地打开和关闭你的文件。像这样的东西更清楚,不会泄漏文件描述符,并且不依赖于实现细节:
def read_json(file): with open(file) as f: return json.load(f)
2条答案
按热度按时间xqkwcwgp1#
它会自动关闭吗?
是的。退出作用域后,引用计数递减,文件描述符关闭。(但是不要试图在Jython中逃避这一点!)
如何验证?
咨询
os.listdir('/proc/self/fd/')
u5rb5r592#
在
open()
的特定情况下,即使您没有将其分配给变量,文件仍然是打开的,并且需要关闭以避免泄漏文件描述符。该文件从open()
返回的那一刻开始打开,而不是在调用__enter__()
时打开。(__enter__()
实际上是内置文件类型的无操作,尽管并非所有上下文管理器都是如此。你可以通过跟踪Python创建的系统调用来看到这一点:
即使没有对变量赋值,也没有使用上下文管理器,仍然调用了
openat()
系统调用。在同一个跟踪中,我们可以看到
close()
系统调用也在之后被调用:这是因为文件描述符没有对它的引用,这会调用垃圾收集器,如果文件句柄没有显式关闭,垃圾收集器也会关闭文件句柄。
然而,依赖CPython的这个实现细节通常被认为是不好的做法。我建议你明确地打开和关闭你的文件。
像这样的东西更清楚,不会泄漏文件描述符,并且不依赖于实现细节: