7

今天早些时候,我问了这个关于__del__()使用导入模块的对象的方法的问题。问题是__del__()想要使用模块os,但有时(并非总是)模块已经被删除。有人告诉我,当 Python 程序终止时,删除对象和模块的顺序可以是随机的,并且是未定义的。但是,对于我的应用程序,我确实需要确保在删除模块(在其中实例化对象)之前删除对象(我创建的类的实例)。有没有办法做到这一点?

4

2 回答 2

14

正如我们之前告诉你的,你真的不应该依赖__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重组代码允许它。

第二种(更好的*)方法是让你的类成为一个上下文管理器,当你退出上下文时执行清理代码。然后您的代码将如下所示:

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 ...
于 2013-02-20T18:10:07.063 回答
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已经清理了其他问题中的函数会失败的原因),而函数本地则与函数对象一起清理,或者在实例属性的情况下,与实例一起清理。

于 2013-02-20T17:55:44.977 回答