我正在尝试调试导致sys.modules['numpy']
被覆盖的问题。我已经向numpy.__init__
添加了一些打印语句,当我尝试导入numpy时,我得到了这个输出:
numpy.__init__ running
id(sys.modules) = 89034704
id(sys.modules['numpy']) = 161528304
numpy.__init__ running
id(sys.modules) = 89034704
id(sys.modules['numpy']) = 177135864
Numpy有许多循环导入,它应该按照this answer中的描述工作。但在我的情况下,不是从sys.modules
获取部分初始化的numpy模块,而是再次导入numpy,第二次执行numpy.__init__
,导致崩溃。
如何设法sys.modules
以便了解谁覆盖sys.modules['numpy']
以及何时?通常我会写一个dict子类,但我不知道认为将sys.modules
更改为指向我自己的对象是安全的。我尝试覆盖sys.modules.__setattr__
,但这是一个只读属性。
上下文:我试图在Julia库PyCall中调试this issue。 PyCall在正在运行的Julia进程中嵌入Python解释器,并将导入委托给cpython中的PyImport_ImportModule
。上面的问题发生在PyImport_ImportModule
的单个调用中,所以我希望这个问题应该对python / cpython的知识负责,但不知道Julia / PyCall。
答案 0 :(得分:2)
您可以将sys.modules
从普通dict
更改为prints
分配,例如:
import sys
import traceback
class noisydict(dict):
def __setitem__(self, key, value):
print('ASSIGNED: key={!r} value={!r} at:'.format(key, value))
traceback.print_stack()
return dict.__setitem__(self, key, value)
sys.modules = noisydict(sys.modules)
如果在C代码中发生覆盖(这样的代码可能直接访问底层的dict.__setitem__
而不是像Python代码那样只执行sys.modules[name] = newmodule
),这可能会也可能不会起作用,但它是值得一试!
答案 1 :(得分:1)
感谢@BrenBarn指点我https://stackoverflow.com/a/14778568/744071。以下是我的目的:
importhack.py:
import traceback
old_import = __import__
def my_import(module, *args, **kwargs):
print "my_import({}) caused by:".format(module)
traceback.print_stack()
return old_import(module, *args, **kwargs)
__builtins__['__import__'] = my_import
用法:
>>> import importhack
>>> import numpy
我相信PyCall.jl中的原始问题是在Python解释器完全初始化之前调用PyImport_ImportModule
引起的。