python - 为什么这样打开文件能自动关闭?
PHP中文网
PHP中文网 2017-04-18 09:41:54
[Python讨论组]
import pprint
pprint.pprint(open(r'c:\text\somefile.txt').readlines())

如上,并没有with啥的,怎么就能自动关闭了呢?

PHP中文网
PHP中文网

认证0级讲师

全部回复(2)
PHP中文网

File object最终会被垃圾回收机制释放和关闭,但不能保证具体什么时候,根据Python的实现释放时机各有不同。
目前CPython使用引用技术做垃圾回收,其他Python(如Jython,Python on JVM)有其他的垃圾回收技术。
如果需要保证文件被及时关闭推荐使用with:

import pprint
with open(r'/tmp/test.log') as f:
    pprint.pprint(f.readlines())

用Python 2.7.5(CPython)来验证下面的代码确实在执行time.sleep之前关闭了文件:

# test.py
import time
import pprint

pprint.pprint(open(r'/tmp/test.log').readlines())
time.sleep(20)

使用lsof查看进程在sleep过程中确实没有引用/tmp/test.log文件:

lsof -p pid

COMMAND  PID  USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
strace  5088 garry  cwd    DIR    8,1     4096 9963923 /home/garry/Projects/python
strace  5088 garry  rtd    DIR   8,20     4096       2 /
strace  5088 garry  txt    REG   8,20   434616  823306 /usr/bin/strace
strace  5088 garry  mem    REG   8,20  2093096  793444 /usr/lib64/libc-2.18.so
strace  5088 garry  mem    REG   8,20   154992  786429 /usr/lib64/ld-2.18.so
strace  5088 garry    0u   CHR  136,1      0t0       4 /dev/pts/1
strace  5088 garry    1u   CHR  136,1      0t0       4 /dev/pts/1
strace  5088 garry    2u   CHR  136,1      0t0       4 /dev/pts/1

使用strace来观察程序系统调用的过程,可以发现确实在读取数据后立刻关闭了文件:

strace python test.py

// 打开文件,fd为3
open("/tmp/test.log", O_RDONLY)         = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=6, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=6, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f45a7bc7000
// 读取文件内容
read(3, "lllll\n", 8192)                = 6
read(3, "", 4096)                       = 0
// 关闭文件
close(3)                                = 0
munmap(0x7f45a7bc7000, 4096)            = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f45a7bc7000
// 输出到终端
write(1, "['lllll\\n']\n", 12['lllll\n']
)          = 12
// 执行sleep
select(0, NULL, NULL, NULL, {20, 0})    = 0 (Timeout)
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f45a73d66d0}, {0x7f45a76f5680, [], SA_RESTORER, 0x7f45a73d66d0}, 8) = 0
exit_group(0)                           = ?
阿神

python解释器自动回收的。
open 打开一个临时 file对象,在读取内容以后,引用计数为0。
解释器回收垃圾时销毁file,文件就关闭了。

大概过程就是这样吧~

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号