为什么赋值给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出来,只是隐约地意识到你可以用它来“重新装载技巧”(甚至有一些重要的陷阱甚至是这种用法)。
我不会写一个非模块,并期望任何东西,但痛苦。 我认为这个配方是完全错误的。