Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
可以依靠引用计数来关闭Python中的文件吗?_Python_File_Garbage Collection_Reference Counting_Resource Leak - Fatal编程技术网

可以依靠引用计数来关闭Python中的文件吗?

可以依靠引用计数来关闭Python中的文件吗?,python,file,garbage-collection,reference-counting,resource-leak,Python,File,Garbage Collection,Reference Counting,Resource Leak,在这个问题“”中,我有以下代码: 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

在这个问题“”中,我有以下代码:

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]
#!/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)
我因为在列表中打开文件而受到批评,一个人认为,如果我有足够长的列表,我将用尽打开的文件句柄。建议使用大大降低了hashfile灵活性的接口,使hashfile具有文件名参数,并将
一起使用

这些是必要的吗?我真的做错了什么吗

测试此代码:

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]
#!/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)
#/usr/bin/python3
导入系统
从pprint导入pprint#漂亮打印
类HereAndGone(对象):
定义初始化(self,i):
打印(“%d%x->即将存在。”%(i,id(self)),
文件=sys.stderr)
self.i=i
定义(自我):
print(“%d%x有人指出了它非常明确地说“当对象变得不可访问时,不要依赖于对象的立即终结(因此您应该始终明确地关闭文件)。”。因此,这表明代码依赖于无法保证的行为

即使是这样,它仍然是脆弱的。它无形中依赖于该文件永远不会被具有循环引用的数据结构引用,或者在对单个文件进行散列之后使用寿命更长的数据结构引用。谁知道将来代码会发生什么,以及是否有人会记住这个关键细节

问题是如何处理它。问题中的
hashfile
函数非常灵活,修改它的接口以获取文件名并让它打开函数中的文件,从而破坏其灵活性,这似乎是一种耻辱。我认为最小的解决方案是:

我觉得解决的办法是重新考虑一下界面,使其更加通用

def hash_bytestr_iter(hasher, bytesiter, ashexstr=False):
    for block in bytesiter:
        hasher.update(bytesiter)
    return (hasher.hexdigest() if ashexstr else hasher.digest())

def iter_and_close_file(afile, blocksize=65536):
    with afile:
        block = afile.read(blocksize)
        while len(block) > 0:
            yield block
可以让原始的
hashfile
使用传入的
afile
作为上下文管理器,但我觉得这种方式微妙地打破了人们的期望。它使
hashfile
关闭文件,它的名称某种程度上承诺它将计算一个哈希,而不是关闭文件

我怀疑在很多情况下,如果你有字节块,你想把它们都散列,就像它们是连续块或字节流的一部分一样。对字节块进行迭代器散列比对文件进行散列更为普遍


类似地,我认为在很多情况下,您希望迭代一个类似文件的对象,然后将其关闭。因此,这使得这两个函数都可重用且通用。

“Python实现是否需要进行某种形式的引用计数?”-否从gc模块的文档来看,引用计数无疑是该语言的一个核心特性。"-大多数gc模块,特别是关于关闭它的部分,应该被视为可选功能。修改
hashfile
,使其具有文件名并处理打开和关闭文件本身。通常使用系统内存管理来管理其他资源是一个糟糕的主意。@tfb-这看起来非常丑陋。为什么一个非常好的通用函数是否可以变成一个非常特殊的函数来控制资源的范围?引用语言参考的“数据模型”一节:当对象变得不可访问时,不要依赖于对象的立即终结(因此您应该始终显式关闭文件)