我发现了一些很奇怪的东西。请参阅下面的简短代码。
import os
class Logger(object):
def __init__(self):
self.pid = os.getpid()
print "os: %s." %os
def __del__(self):
print "os: %s." %os
def temp_test_path():
return "./[%d].log" %(os.getpid())
logger = Logger()
这是出于说明目的。它只是打印导入的模块os
,关于类的构建和破坏(更不用说名称Logger
)。但是,当我运行它时,模块os
似乎在类析构函数中“消失”到None
。以下是输出。
os: <module 'os' from 'C:\Python27\lib\os.pyc'>.
os: None.
在哪里说os: None.
是我的问题。它应该与第一个输出线相同。但是,回顾上面的python代码,在函数temp_test_path()
。如果我稍微改变这个函数的名称,说temp_test_pat()
,并保持所有其余的代码完全相同,并运行它,我得到预期的输出(下面)。
os: <module 'os' from 'C:\Python27\lib\os.pyc'>.
os: <module 'os' from 'C:\Python27\lib\os.pyc'>.
除了这是一个错误之外,我找不到任何解释。你能?顺便说一句,我使用的是Windows 7 64位。
答案 0 :(得分:4)
如果您依靠解释器关闭来呼叫__del__
,那么os
模块在您__del__
被调用之前就已经被删除了。尝试在代码中明确地执行del logger
并稍微休眠一下。这应该清楚地表明代码按预期运行。
我还想将您链接到official documentation中的这个注释,__del__
不保证在CPython实现中调用{{1}}。
答案 1 :(得分:3)
我转载了这个。有趣的行为肯定。您需要意识到的一件事是,当解释器退出时,甚至不能保证__del__
被调用 - 而且在解释器出口处没有指定的完成对象的命令。
由于您已退出解释程序,因此无法保证先未删除os
。在这种情况下,似乎os
实际上是在Logger
对象之前完成的。根据{{1}}字典中的顺序,可能会发生这些事情。
如果我们只是在退出之前打印全局词典的键:
globals
你会看到:
for k in globals().keys():
print k
或:
temp_test_path
__builtins__
__file__
__package__
__name__
Logger
os
__doc__
logger
请注意logger
__builtins__
__file__
__package__
temp_test_pat
__name__
Logger
os
__doc__
所在的位置,特别是与logger
位于列表中的位置相比较。使用os
,temp_test_pat
实际上已完成第一次,因此logger
仍然绑定了有意义的内容。但是,如果您使用os
,则会最终确定上次。
如果您计划在解释器退出之前有一个对象,并且您有一些要运行的清理代码,则可以始终使用temp_test_path
注册要运行的函数。
答案 2 :(得分:3)
其他人已经给出了答案,未定义全局变量(例如os
,Logger
和logger
)在关闭期间从模块的命名空间中删除的顺序。 / p>
但是,如果您想要一种解决方法,只需将os
导入到终结者的本地命名空间中:
def __del__(self):
import os
print "os: %s." %os
os
模块此时仍然存在,只是您丢失了对它的全局引用。
答案 3 :(得分:2)
这是可以预料的。来自Python Language Reference:
此外,在响应正在删除的模块时调用 del () (例如,当完成程序的执行时),其他全局变量 由 del ()方法引用可能已被删除或删除 被拆除的过程(例如进口机械关闭) 向下)。
在大红色警告框中: - )