Python 2.7可能的bug,导入的模块“消失”

时间:2013-02-20 15:50:17

标签: python

我发现了一些很奇怪的东西。请参阅下面的简短代码。

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位。

4 个答案:

答案 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位于列表中的位置相比较。使用ostemp_test_pat实际上已完成第一次,因此logger仍然绑定了有意义的内容。但是,如果您使用os,则会最终确定上次

如果您计划在解释器退出之前有一个对象,并且您有一些要运行的清理代码,则可以始终使用temp_test_path注册要运行的函数。

答案 2 :(得分:3)

其他人已经给出了答案,未定义全局变量(例如osLoggerlogger)在关闭期间从模块的命名空间中删除的顺序。 / p>

但是,如果您想要一种解决方法,只需将os导入到终结者的本地命名空间中:

def __del__(self):
    import os
    print "os: %s." %os

os模块此时仍然存在,只是您丢失了对它的全局引用。

答案 3 :(得分:2)

这是可以预料的。来自Python Language Reference

  

此外,在响应正在删除的模块时调用 del ()   (例如,当完成程序的执行时),其他全局变量   由 del ()方法引用可能已被删除或删除   被拆除的过程(例如进口机械关闭)   向下)。

在大红色警告框中: - )