分配给sys.modules [__ name__]后,为什么__name__的值会发生变化?
问题内容:
尝试执行类似于Alex
Martelli的ActiveState食谱(名为Python中的Constants)的方法时,我遇到了意外的副作用(在Python
2.7中),该副作用将类实例分配给sys.modules
has中的条目-即,这样做显然如以下代码片段所示更改__name__
to的值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
模块中的每个变量来完成(这是因为pythonNone
在删除模块时会将所有变量都设置在模块中)。
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'>
希望这能解释一切。