所以,我有一个目录结构:
main.py
\_ modules/
\_ a.py
\_ b.py
在 main.py 中,模块在运行时动态加载,具体取决于指定的模块。 (这允许添加假设的 c.py
,重新运行 main.py
,以及程序检测 c.py
的添加并运行它。)
问题是 b.py
导入通过 pip 安装的模块(在 virtualenv 中)。 (我将把它称为一个库,以避免混淆。)当 b.py
直接运行( python b.py
)库导入就好了。当外壳打开并手动导入库时,它就可以工作。
但是,当 main.py
运行并 b.py
动态导入(使用 pkgutil.iter_modules
检测模块,然后 importlib.import_module
导入所需的模块), b.py
的库找不到导入 - ImportError: No module
被抛出。
回顾一下:模块导入已安装的库,当直接运行模块或在 python 解释器中手动导入有问题的库时,这是有效的,但是当动态导入模块时,找不到该库。给出了什么?
最佳答案
第三个不相关的细节是问题:pyenv。
有一个错误报告 here ,但长话短说是 pyenv 使用垫片来拦截包导入并正确路由它们。
这意味着 pyenv 必须混淆路径。当我直接运行 python 时,填充程序在 python 路径中很明显:
[dnelson@blueharvest somedir]$ python
Python 2.7 (r27:82500, Jun 1 2015, 15:01:57)
[GCC 4.9.2 20150212 (Red Hat 4.9.2-6)] on linux3
Type "help", "copyright", "credits" or "license" for more information.
>>> import site
>>> site.getsitepackages()
['/home/dnelson/.pyenv/versions/2.7/lib/python2.7/site-packages', '/home/dnelson/.pyenv/versions/2.7/lib/site-python']
>>> site.PREFIXES
['/home/dnelson/.pyenv/versions/2.7', '/home/dnelson/.pyenv/versions/2.7']
>>>
但是,在动态导入的包中,相同的代码会产生以下输出:
['/usr/lib64/python2.7/site-packages', '/usr/lib/python2.7/site-packages', '/usr/lib/site-python']
['/usr', '/usr']
因此,问题似乎是 pyenv 在动态导入期间没有发挥其垫片魔力。
为了解决这个问题,我使用 pip install --user
强制 pip 安装到动态导入所查找的位置,而不是 pyenv 希望安装的位置。 (如果您之前安装过该软件包,还可以添加 -I
以强制重新安装)
也可以通过使用 sys.path 将安装位置(在我的例子中为
,但这闻起来很糟糕,并且可能会给其他人带来问题。/usr/lib/python2.7/site-packages
)附加到 python 路径来解决。附加
关于Python动态导入在Virtualenv中找不到包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31602160/