为什么分配给 sys.modules[__name__] 后 __name__ 的值会改变?
- 2025-03-21 09:05:00
- admin 原创
- 42
问题描述:
在尝试执行与 Alex Martelli 撰写的 ActiveState 配方Python 中的常量中类似的操作时,我遇到了意外的副作用(在 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__':
条件显然在赋值后按预期工作(但现在不再如此)。
值得一提的是,我还注意到,在分配之后,名称_test
也从类对象重新绑定到。它们被重新绑定到而不是完全消失,这对我来说似乎很奇怪...None
`None`
更新:
我想补充一点,如果能提供任何能达到 效果的解决方法if __name__ == '__main__':
,考虑到发生的情况,我们将不胜感激。TIA!
解决方案 1:
发生这种情况是因为您覆盖了模块,因此sys.modules[__name__] = _test()
您的模块被删除了(因为模块不再有任何对它的引用,并且引用计数器变为零,所以它被删除),但与此同时解释器仍然有字节码,所以它仍然可以工作,但是会返回None
到模块中的每个变量(这是因为None
当删除模块时,python 会将所有变量设置为在模块中)。
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'>
希望这可以解释事情。
解决方案 2:
如果我分配任何东西,sys.modules['__main__']
我就会得到一个严重损坏的环境。不是这个确切的行为,但我的所有全局变量和内置变量都会消失。
sys.modules
没有记录表明在写入时会以任何特定的方式运行,只有模糊地说明你可以使用它来“重新加载技巧”(并且即使是这种用法也存在一些重大陷阱)。
我不会为它编写非模块,而且除了痛苦之外什么都做不到。我认为这个方法完全是误导。
扫码咨询,免费领取项目管理大礼包!