打开一个文件作为字典构造的一部分之后会关闭它吗?

Does opening a file as part of a dictionary construction close it afterwards?

我在处理 Python 请求库时见过这种语法:

body = { file_name: open(file_path, 'rb') }

我想知道这是否会关闭文件,因为我多次看到它是这样写的。

将我的评论重新发布为已接受的答案:

它基本上是这样的:当 open() 返回的文件对象不再有对它的引用时,文件将被关闭。在这种情况下,字典保留了一个引用,但同样地,当没有剩余的字典引用时,它也会在文件超出范围时删除对该文件的引用。这可能会导致错误,文件句柄保持打开状态。 Python 如果您 运行 和 python -Wall 3 将对此发出警告。对于只读文件,它基本上是无害的,因为没有数据要刷新到磁盘。但我还是会避免这种情况。

例如:

$ python3 -Wall
Python 3.6.9 (default, Nov  7 2019, 10:44:02) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> {'f': open('.bashrc')}
{'f': <_io.TextIOWrapper name='.bashrc' mode='r' encoding='UTF-8'>}
>>> exit()
sys:1: ResourceWarning: unclosed file <_io.TextIOWrapper name='.bashrc' mode='r' encoding='UTF-8'>

实际上你甚至不需要 dict:

$ python3 -Wall
Python 3.6.9 (default, Nov  7 2019, 10:44:02) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> open('.bashrc')
<_io.TextIOWrapper name='.bashrc' mode='r' encoding='UTF-8'>
>>> exit()
sys:1: ResourceWarning: unclosed file <_io.TextIOWrapper name='.bashrc' mode='r' encoding='UTF-8'>

这是因为在最后一种情况下,REPL 中最后返回的值存储在特殊变量_.

事实上,这个 ResourceWarning 会在文件对象的 __del__ 被显式关闭之前被调用时引发:

$ python3 -Wall
Python 3.6.9 (default, Nov  7 2019, 10:44:02) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> f = open('.bashrc')
>>> del f
__main__:1: ResourceWarning: unclosed file <_io.TextIOWrapper name='.bashrc' mode='r' encoding='UTF-8'>

这只是一个警告(默认情况下禁用),因为它通常不是一个严重的问题,因为文件仍将关闭。但它 可能 表示一个错误,但是在调试文件 I/O 问题时启用此警告是很好的,并且也可以像一般那样使用 with 语句打开文件好的做法:

>>> with open(file_path, 'rb') as fobj:
...     body = { file_name: fobj }
...     # send request, etc...