【发布时间】:2017-05-13 13:02:24
【问题描述】:
在这个问题“Generating an MD5 checksum of a file”中,我有这个代码:
import hashlib
def hashfile(afile, hasher, blocksize=65536):
buf = afile.read(blocksize)
while len(buf) > 0:
hasher.update(buf)
buf = afile.read(blocksize)
return hasher.digest()
[(fname, hashfile(open(fname, 'rb'), hashlib.sha256())) for fname in fnamelst]
我因在列表解析中打开文件而受到批评,有人认为如果我有足够长的列表,我会用完打开的文件句柄。建议使用显着降低 hashfile 的灵活性并让 hashfile 采用文件名参数并使用 with 的接口。
这些有必要吗?我真的做错了什么吗?
测试这段代码:
#!/usr/bin/python3
import sys
from pprint import pprint # Pretty printing
class HereAndGone(object):
def __init__(self, i):
print("%d %x -> coming into existence." % (i, id(self)),
file=sys.stderr)
self.i_ = i
def __del__(self):
print("%d %x <- going away now." % (self.i_, id(self)),
file=sys.stderr)
def do_nothing(hag):
return id(hag)
l = [(i, do_nothing(HereAndGone(i))) for i in range(0, 10)]
pprint(l)
结果如下:
0 7f0346decef0 -> coming into existence.
0 7f0346decef0 <- going away now.
1 7f0346decef0 -> coming into existence.
1 7f0346decef0 <- going away now.
2 7f0346decef0 -> coming into existence.
2 7f0346decef0 <- going away now.
3 7f0346decef0 -> coming into existence.
3 7f0346decef0 <- going away now.
4 7f0346decef0 -> coming into existence.
4 7f0346decef0 <- going away now.
5 7f0346decef0 -> coming into existence.
5 7f0346decef0 <- going away now.
6 7f0346decef0 -> coming into existence.
6 7f0346decef0 <- going away now.
7 7f0346decef0 -> coming into existence.
7 7f0346decef0 <- going away now.
8 7f0346decef0 -> coming into existence.
8 7f0346decef0 <- going away now.
9 7f0346decef0 -> coming into existence.
9 7f0346decef0 <- going away now.
[(0, 139652050636528),
(1, 139652050636528),
(2, 139652050636528),
(3, 139652050636528),
(4, 139652050636528),
(5, 139652050636528),
(6, 139652050636528),
(7, 139652050636528),
(8, 139652050636528),
(9, 139652050636528)]
很明显,每个HereAndGone 对象都在构造列表推导式的每个元素时被创建和销毁。一旦没有对它的引用,Python 引用计数就会释放该对象,这会在计算该列表元素的值之后立即发生。
当然,也许其他一些 Python 实现不这样做。 Python 实现是否需要进行某种形式的引用计数?从gc 模块的文档看来,引用计数确实是该语言的核心特性。
而且,如果我确实做错了什么,你会建议我如何重写它以保持列表理解的简洁明了和界面的灵活性,该界面适用于任何可以像文件一样读取的内容?
【问题讨论】:
-
“Python 实现是否需要进行某种形式的引用计数?” - 没有。
-
“从 gc 模块的文档看来,引用计数确实是该语言的核心特性。” - 大多数 gc 模块,尤其是关于关闭它的部分,应该被视为可选功能。
-
修改
hashfile,使其采用文件名并处理文件本身的打开和关闭。一般而言,使用系统的内存管理来管理其他资源是一个糟糕的主意。 -
@tfb - 这看起来非常丑陋。为什么要把一个非常好的通用功能变成一个非常特定用途的功能,只是为了控制资源的范围?
-
引用语言参考的“数据模型”部分:当对象变得不可访问时,不要依赖于立即完成(因此您应该始终明确关闭文件)跨度>
标签: python file garbage-collection reference-counting resource-leak