所以,我有一个目录结构:
main.py
\_ modules/
\_ a.py
\_ b.py
在main.py中,模块在运行时动态加载,具体取决于指定的模块。 (这允许添加假设的c.py
,重新运行main.py
,以及检测添加c.py
并运行它的程序。)
问题是b.py
导入通过pip安装的模块(在virtualenv中)。 (我将它称为库以帮助避免混淆。)当b.py
直接运行(python b.py
)时,库导入就好了。打开shell并手动导入库时,它可以正常工作。
但是,当运行main.py
并动态导入b.py
时(使用pkgutil.iter_modules
检测模块,然后importlib.import_module
导入所需的模块),库<{1}}导入未找到 - b.py
被抛出。
回顾一下:一个模块导入一个已安装的库,这在模块直接运行时或者在python解释器中手动导入有问题的库时有效,但是当动态导入模块时,库不是。找到了。是什么给了什么?
答案 0 :(得分:1)
第三个不相关的细节是问题: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
也可以通过使用/usr/lib/python2.7/site-packages
将安装位置(在我的情况下,sys.path.append
)附加到python路径来解决这个问题,但这种情况很糟糕,并且可能导致其他人的问题。
答案 1 :(得分:0)
Virtualenvs臭名昭着。他们多次修补路径并搞砸了很多东西。
在两种情况下,您都需要检查PATH
内的b.py
变量。
这很可能不一样。
您需要设置包含c.py
目录的路径。
您可以在main.py
中查看PATH,如果它在那里是正确的,则表示您的其他导入之一正在更改sys.path
以便删除它。