我试图通过sys.meta_path
设置一些导入钩子,类似于这个SO问题的方法。为此,我需要定义两个函数find_module
和load_module
,如上面的链接所解释的那样。这是我的load_module
函数:
import imp
def load_module(name, path):
fp, pathname, description = imp.find_module(name, path)
try:
module = imp.load_module(name, fp, pathname, description)
finally:
if fp:
fp.close()
return module
这对大多数模块都有效,但在使用Python 2.7时,对于PyQt4.QtCore
失败了:
name = "QtCore"
path = ['/usr/lib64/python2.7/site-packages/PyQt4']
mod = load_module(name, path)
返回
Traceback (most recent call last):
File "test.py", line 19, in <module>
mod = load_module(name, path)
File "test.py", line 13, in load_module
module = imp.load_module(name, fp, pathname, description)
SystemError: dynamic module not initialized properly
同样的代码在Python 3.4中运行良好(尽管
imp
被弃用,应该使用importlib
代替)。我想这可能与SIP动态模块初始化有关。在Python 2.7中是否还有其他我应该尝试的东西?注意:这适用于
PyQt4
和PyQt5
。
编辑:这可能与此问题有关,因为实际上,cd /usr/lib64/python2.7/site-packages/PyQt4
python2 -c 'import QtCore'
出现了相同的错误。 我仍然不确定有什么方法可以解决它...
编辑2: 以下是@Nikita要求的具体用例示例,我试图做的是重定向导入,因此当执行import A
时,发生的情况是import B
。 人们可能确实认为,在find_spec/find_module
中进行模块重命名,然后使用默认的load_module
就足够了。 然而,在Python 2中,不清楚在哪里找到默认的load_module
实现。 我找到的与之类似的最接近的实现是future.standard_library.RenameImport
。 看起来没有将Python 3中的完整importlib
实现移植到2中的后备。
可以在此gist中找到重现此问题的导入钩子的最小工作示例。
__import__('PyQt4.QtCore')
有什么问题吗?会导致无限递归吗? - danidee__import__('A')
没有问题,但它等同于使用import A
。我想要的是在你执行import A
时改变发生的事情,特别是运行import B
。这可以通过sys.meta_path
中的导入钩子来完成,但它们需要更低级别的函数,如imp.load_module
。 - rthimporylib
文档中写道:“这个模块是Python 3.1中同名更全面的包中可用内容的一个小子集,它提供了import的完整实现。”关于自定义导入的想法在PEP302中有所涉及,我会研究一下并在答案更新中分享我的想法。 - Nikita