今天早些时候,我问了this关于使用导入模块的对象的__del__()
方法的问题。问题是__del__()
想要使用模块os
,但有时(并非总是)模块已被删除。有人告诉我,当Python程序终止时,删除对象和模块的顺序可能是随机的,并且是未定义的。但是,对于我的应用程序,我确实需要确保在模块(实例化对象)之前删除对象(我创建的类的实例)。有没有办法做到这一点?
答案 0 :(得分:10)
正如我们之前告诉过你的那样,当解释器退出时,你真的不应该依赖__del__
被调用。正确执行此操作有两种选择:
第一个是atexit
import os
import atexit
class Logger(object):
def on_exit(self):
print "os: %s." % os
logger = Logger()
atexit.register(logger.on_exit)
这可确保您的记录器在退出时完成。
*在您的问题中阅读更多内容,因为您计划将单个实例绑定到定义实例类的模块,下面的上下文管理器解决方案将不适用于此,因为无法保留在上下文中用于整个程序的执行。您需要使用atexit.register
。但是,从程序设计的角度来看,如果重构代码允许,我更倾向于使用上下文管理器来管理我的资源而不是atexit.register
。
第二个(更好*)方法是让你的类成为context manager,当你退出上下文时它会执行清理代码。然后你的代码看起来像:
import os
class Logger(object):
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
print "os:",str(os)
with Logger() as logger:
#do something ...
答案 1 :(得分:4)
使用关键字参数附加对函数的引用:
import os
class Logger(object):
def __del__(self, os=os):
print "os: %s." %os
或将其绑定到类属性:
import os
class Logger(object):
def __init__(self):
self.os = os
def __del__(self):
print "os: %s." % self.os
通过创建本地(足够)引用,Python不会将os
视为全局,而是使用本地引用,它们分别与实例或函数本身一起存储。
在运行时查找全局变量(这就是为什么如果__del__
已经被清除,则另一个问题中的os
函数失败),而函数local与函数对象一起被清除,或者在实例属性的情况下,与实例。