如何调试被覆盖的 sys.modules 条目?
How to debug a sys.modules entry that gets overwritten?
我正在尝试调试导致 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 解释器,并将导入委托给 PyImport_ImportModule
from cpython。上面的问题发生在对 PyImport_ImportModule
的一次调用中,所以我希望这个问题应该在 python / cpython 的知识下回答,但不了解 Julia / PyCall。
您可以将 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
)但值得一试!
感谢@BrenBarn 将我指向 。以下内容适用于我的目的:
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
引起的。
我正在尝试调试导致 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 解释器,并将导入委托给 PyImport_ImportModule
from cpython。上面的问题发生在对 PyImport_ImportModule
的一次调用中,所以我希望这个问题应该在 python / cpython 的知识下回答,但不了解 Julia / PyCall。
您可以将 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
)但值得一试!
感谢@BrenBarn 将我指向 。以下内容适用于我的目的:
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
引起的。