Spe*_*bun 10 python garbage-collection resource-cleanup
我有一个包含我需要的文件处理功能的类.另一个类创建了一个实例,filehandler并在不确定的时间内使用它.最终,它caller被摧毁了,它摧毁了唯一的引用filehandler.
filehandler关闭文件的最佳方法是什么?
我目前使用__del__(self)但在看到几个 不同的 问题 和文章后,我认为这被认为是一件坏事.
class fileHandler:
def __init__(self, dbf):
self.logger = logging.getLogger('fileHandler')
self.thefile = open(dbf, 'rb')
def __del__(self):
self.thefile.close()
Run Code Online (Sandbox Code Playgroud)
这是处理程序的相关部分.该类的重点是抽象出使用底层文件对象的细节,并避免不必要地将整个文件读入内存.但是,处理底层文件的一部分是在对象超出范围时关闭它.
本caller不应该知道或关心参与的细节filehandler.filehandler当它超出范围时,释放所涉及的任何必要资源是我们的工作.这是它首先被抽象的原因之一.所以,我似乎面临着将filehandler代码移动到调用对象或处理漏洞抽象的问题.
思考?
Eth*_*man 14
__del__本身并不是一件坏事.您必须格外小心,不要在已__del__定义的对象中创建引用循环.如果您确实发现自己需要创建循环(父级指的是引用父级的子级),那么您将需要使用该weakref模块.
所以,__del__没关系,只要警惕cylic引用.
垃圾收集:这里最重要的一点是,当一个对象超出范围时,它可以被垃圾收集,而事实上,它会被垃圾收集......但什么时候?不能保证何时,不同的Python实现在这个领域有不同的特性.因此,对于管理资源,最好是明确地添加.close()您的filehandler或者,如果您的使用是兼容的,添加__enter__和__exit__方法.
该__enter__和__exit__方法如下所述.关于它们的一个非常好的事情是,__exit__即使发生异常也会调用它,因此您可以优雅地计算或关闭资源.
您的代码,增强了__enter__/ __exit__:
class fileHandler:
def __init__(self, dbf):
self.logger = logging.getLogger('fileHandler')
self.thefilename = dbf
def __enter__(self):
self.thefile = open(self.thefilename, 'rb')
return self
def __exit__(self, *args):
self.thefile.close()
Run Code Online (Sandbox Code Playgroud)
请注意,正在打开文件__enter__而不是__init__- 这允许您创建一次文件处理程序对象,然后在with不需要重新创建它时随时使用它:
fh = filehandler('some_dbf')
with fh:
#file is now opened
#do some stuff
#file is now closed
#blah blah
#need the file again, so
with fh:
# file is open again, do some stuff with it
#etc, etc
Run Code Online (Sandbox Code Playgroud)
正如您所写的那样,该类不会使文件更可靠地关闭.如果你简单地将文件处理程序实例放在地板上,那么在对象被销毁之前文件将不会关闭.这可能是直接或者可能不是,直到对象被垃圾收集,但只是将普通文件对象放在地板上就会快速关闭它.如果唯一的引用thefile是来自你的类对象内部,那么当filehandler垃圾收集thefile时也会被垃圾收集,因此同时关闭.
使用文件的正确方法是使用以下with语句:
with open(dbf, 'rb') as thefile:
do_something_with(thefile)
Run Code Online (Sandbox Code Playgroud)
这将保证thefile在with子句退出时始终关闭.如果要将文件包装在另一个对象中,也可以通过定义__enter__和__exit__方法来完成:
class FileHandler:
def __init__(self, dbf):
self.logger = logging.getLogger('fileHandler')
self.thefile = open(dbf, 'rb')
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
self.thefile.close()
Run Code Online (Sandbox Code Playgroud)
然后你可以这样做:
with FileHandler(dbf) as fh:
do_something_with(fh)
Run Code Online (Sandbox Code Playgroud)
并确保文件立即关闭.
| 归档时间: |
|
| 查看次数: |
2703 次 |
| 最近记录: |