在尝试做类似于Alex Martelli标题为Constants in Python的ActiveState配方中的内容时,我遇到了意外的副作用(在Python 2.7中),它将类实例分配给{{1 } has - 即这样做显然会将sys.modules
的值更改为__name__
,如下面的代码片段所示(它会破坏配方中的部分代码):
None
我想了解为什么会这样。我不相信它在Python 2.6和早期版本中是这样的,因为我有一些较旧的代码,显然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"
条件在赋值后按预期工作(但不再有)。
FWIW,我还注意到,在分配之后,名称if __name__ == '__main__':
也会从类对象反弹到_test
。对我来说,他们被反弹到None
而不是完全消失似乎很奇怪......
更新
我想补充一点,为实现None
的效果,任何变通方法都会非常感激。 TIA!
答案 0 :(得分:28)
发生这种情况是因为你在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'>
希望这能解释一切。
答案 1 :(得分:-1)
如果我向sys.modules['__main__']
分配任何内容,我会遇到严重破坏的环境。不是这个确切的行为,但我的所有全局变量和内置函数都消失了。
sys.modules
没有记录在写入时以任何特定方式运行,只是模糊地说你可以用它来“重新加载技巧”(并且甚至对于这种用法也有一些重要的陷阱)。
我不会写一个非模块,并期待除了痛苦之外的任何事情。我认为这个食谱完全被误导了。