【发布时间】:2016-08-12 09:29:15
【问题描述】:
我正在尝试设置一些import hooks 到sys.meta_path,方法与this SO question 有点相似。为此,我需要定义两个函数 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。
编辑:这可能确实与this question 有关,
cd /usr/lib64/python2.7/site-packages/PyQt4
python2 -c 'import QtCore'
失败并出现同样的错误。我仍然不确定有什么方法可以解决它......
Edit2:按照 @Nikita 的具体用例示例的请求,我想做的是重定向导入,所以当有人这样做时 @987654344 @,发生的是import B。确实可以认为,为此在find_spec/find_module 中进行模块重命名就足够了,然后使用默认的load_module。但是,尚不清楚在 Python 2 中在哪里可以找到默认的 load_module 实现。我发现的最接近的类似实现是 future.standard_library.RenameImport。从 Python 3 到 2 似乎没有 importlib 的完整实现的反向移植。
可以在gist 中找到重现此问题的导入挂钩的最小工作示例。
【问题讨论】:
-
如果它可能有用,为我正在尝试做的事情提供一些一般背景,请参阅SiQt 包,this github issue 中讨论了这个问题。
-
我真的不明白你的问题,但
__import__('PyQt4.QtCore')有什么问题。会导致无限递归吗? -
@danidee
__import__('A')没什么问题,但它相当于使用import A。我想要的是改变当你这样做时会发生什么,特别是当你import A时运行import B。这可以通过sys.meta_path中的导入挂钩来完成,但它们需要较低级别的函数,例如imp.load_module。 -
@rth,确实在 Python 2.7 中关于
imporylib的文档中写道:“此模块是功能更齐全的同名包中可用功能的一小部分来自 Python 3.1,它提供了完整的导入实现。”。 PEP302 中有关于自定义导入的想法,我会看看它并在答案更新中分享我的想法。
标签: python python-2.7 pyqt python-sip