在尝试执行类似于 ActiveState 配方中标题为 Constants in Python 的操作时通过 Alex Martelli,我遇到了意想不到的副作用(在 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__':
效果的任何变通方法,我们将不胜感激。蒂亚!
最佳答案
发生这种情况是因为您在执行 sys.modules[__name__] = _test()
时覆盖了您的模块,因此您的模块被删除了(因为该模块不再有任何对它的引用,并且引用计数器归零,所以它被删除了)但同时解释器仍然有字节码,所以它仍然可以工作,但是通过将 None
返回到模块中的每个变量(这是因为 python 设置删除时模块中的所有变量都为 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'>
希望这能说明问题。
关于python - 为什么分配给 sys.modules[__name__] 后 __name__ 的值会发生变化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5365562/