为什么在分配给sys.modules[\uuu name_uuu]之后uu name_uuu的值会更改?

2024-05-28 20:26:01 发布

您现在位置:Python中文网/ 问答频道 /正文

当尝试做一些类似于亚历克斯·马泰利的ActiveState菜谱中的Constants in Python时,我遇到了意外的副作用(在Python2.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"

我想知道为什么会这样。我不相信在Python2.6和更早的版本中是这样的,因为我有一些较旧的代码,显然if __name__ == '__main__':条件在赋值后按预期工作(但不再这样)。

FWIW,我还注意到名称_test在赋值之后也从类对象反弹到了None。我觉得奇怪的是,它们正在反弹到None而不是完全消失。。。

更新:

我想补充一点,任何能达到if __name__ == '__main__':效果的解决办法,如果发生了什么,我将不胜感激。蒂亚!


Tags: 代码nameintestimportnonemodulesif
2条回答

发生这种情况的原因是,当您执行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'>

希望这能解释一切。

如果我给sys.modules['__main__']分配任何东西,就会得到一个严重损坏的环境。不是这样的行为,但我所有的地球仪和内置设备都消失了。

sys.modules没有记录在案时以任何特定方式进行操作,只是含糊地说,您可以使用它来“重新加载技巧”(甚至对于这种用法也有一些重要的陷阱)。

我不会写一个非模块到它和期望任何东西,除了痛苦。我认为这个食谱完全被误导了。

相关问题 更多 >

    热门问题