为什么赋值给sys.modules 后__name__的值发生了变化?

在尝试做类似于由Alex Martelli命名为“ Constants in Python ”的ActiveState配方时,我遇到了一个意想不到的副作用(在Python 2.7中),它将一个类实例分配给sys.modules的条目 – 即这样做显然会将__name__的值更改为None如以下代码段所示(这会中断配方中的部分代码):

 class _test(object): pass import sys print '# __name__: %r' % __name__ # __name__: '__main__' sys.modules[__name__] = _test() print '# __name__: %r' % __name__ # __name__: None if __name__ == '__main__': # never executes... import test print "done" 

我想了解为什么会发生这种情况。 我不相信这是Python 2.6和更早版本的方式,因为我有一些旧的代码,显然if __name__ == '__main__':条件按照预期工作(但不再是)。

FWIW,我也注意到_test这个名字在赋值之后也从类对象反弹到None 。 对我来说,他们正在被反弹到None而不是完全消失,这似乎很奇怪。

更新:

我想补充说明的是,为了实现if __name__ == '__main__':的效果,给出的结果将不胜感激。 TIA!

发生这种情况是因为当你执行了sys.modules[__name__] = _test()时,你已经覆盖了你的模块,所以你的模块被删除了(因为模块没有任何引用,引用计数器为零,所以它被删除)但同时解释器仍然有字节码,所以它仍然可以工作,但是通过将None返回给模块中的每个variables(这是因为python在删除模块时将所有variables设置为None )。

 class _test(object): pass import sys print sys.modules['__main__'] # <module '__main__' from 'test.py'> <<< the test.py is the name of this module sys.modules[__name__] = _test() # Which is the same as doing sys.modules['__main__'] = _test() but wait a # minute isn't sys.modules['__main__'] was referencing to this module so # Oops i just overwrite this module entry so this module will be deleted # it's like if i did: # # import test # __main__ = test # del test # __main__ = _test() # test will be deleted because the only reference for it was __main__ in # that point. print sys, __name__ # None, None import sys # i should re import sys again. print sys.modules['__main__'] # <__main__._test instance at 0x7f031fcb5488> <<< my new module reference. 

编辑:

一个修补程序将是这样做的:

 class _test(object): pass import sys ref = sys.modules[__name__] # Create another reference of this module. sys.modules[__name__] = _test() # Now when it's overwritten it will not be # deleted because a reference to it still # exists. print __name__, _test # __main__ <class '__main__._test'> 

希望这将解释的事情。

如果我把任何东西分配给sys.modules['__main__']我会得到一个严重的破坏的环境。 不是这个确切的行为,但是我所有的全局variables和内buildvariables都消失了。

sys.modules在写入时没有被logging为以任何特定的方式performance出来,只是隐约地意识到你可以用它来“重新装载技巧”(甚至有一些重要的陷阱甚至是这种用法)。

我不会写一个非模块,并期望任何东西,但痛苦。 我认为这个配方是完全错误的。