为什么 Python `pip.main(['install', ...])` 给出 ImportError,但仅针对带点的包名称?
Why does Python `pip.main(['install', ...])` give ImportError, but only for package names with dot?
当运行下面的代码(Python2.7.12,在Linux上使用sudo -H
),开始的情况是包'plaitpy' 'bda.basen' 从未安装过,
import sys
import os
# The following code successfully installs bda.basen, then fails to import it.
# However, it works for plaitpy (a random recently updated package).
assert '/usr/local/lib/python2.7/dist-packages' in sys.path
import pip
pip.main(['install', 'plaitpy', 'bda.basen'])
assert '/usr/local/lib/python2.7/dist-packages' in sys.path
assert os.path.isfile('/usr/local/lib/python2.7/dist-packages/plaitpy/__init__.py')
import plaitpy # this succeeds, as expected
print plaitpy
assert os.path.isfile('/usr/local/lib/python2.7/dist-packages/bda/basen/__init__.py')
import bda.basen # THIS FAILS WITH 'ImportError: No module named bda.basen'
print bda.basen
然后最后一个 import
语句失败 ImportError: No module named bda.basen
。
根据一些实验,这似乎发生在名称中包含点的每个包(如 bda.basen
和 ruamel.yaml
),并且仅发生在那些包中。
我的问题:为什么?以及如何解决这个问题?
完整的可运行代码(将更新您的系统范围的包!)位于 https://gist.github.com/marnix/2f4efc1154547103bcec3783e6015bfc。
bda
是一个 namespace package,因此不包含 bda/__init__.py
,因此在您重新启动解释器之前,无法在 Python 2 中导入该包或手动调用 site.main()
。这是因为在您的 site-packages
中创建了一个 .pth
文件,它告诉 Python 这是一个其他模块所在的名称空间。当解释器启动时,所有 .pth
文件都由 site.main()
加载,但由于你的文件是在解释器启动之后创建的,Python 不知道它。
In [1]: import pip
In [2]: pip.main(['install', 'bda.basen'])
Collecting bda.basen
Requirement already satisfied: setuptools in /usr/local/lib/python2.7/site-packages (from bda.basen)
Installing collected packages: bda.basen
Successfully installed bda.basen-1.1
Out[2]: 0
In [3]: import bda.basen
---------------------------------------------------------------------------
ImportError Traceback (most recent call last)
<ipython-input-3-e9d84961fc34> in <module>()
----> 1 import bda.basen
ImportError: No module named bda.basen
In [4]: import site
In [5]: site.main()
In [6]: import bda.basen
In [7]:
Python 3.3+ 的行为符合您的预期,因为它本机支持命名空间包并且不需要您调用 site.main()
.
当运行下面的代码(Python2.7.12,在Linux上使用sudo -H
),开始的情况是包'plaitpy' 'bda.basen' 从未安装过,
import sys
import os
# The following code successfully installs bda.basen, then fails to import it.
# However, it works for plaitpy (a random recently updated package).
assert '/usr/local/lib/python2.7/dist-packages' in sys.path
import pip
pip.main(['install', 'plaitpy', 'bda.basen'])
assert '/usr/local/lib/python2.7/dist-packages' in sys.path
assert os.path.isfile('/usr/local/lib/python2.7/dist-packages/plaitpy/__init__.py')
import plaitpy # this succeeds, as expected
print plaitpy
assert os.path.isfile('/usr/local/lib/python2.7/dist-packages/bda/basen/__init__.py')
import bda.basen # THIS FAILS WITH 'ImportError: No module named bda.basen'
print bda.basen
然后最后一个 import
语句失败 ImportError: No module named bda.basen
。
根据一些实验,这似乎发生在名称中包含点的每个包(如 bda.basen
和 ruamel.yaml
),并且仅发生在那些包中。
我的问题:为什么?以及如何解决这个问题?
完整的可运行代码(将更新您的系统范围的包!)位于 https://gist.github.com/marnix/2f4efc1154547103bcec3783e6015bfc。
bda
是一个 namespace package,因此不包含 bda/__init__.py
,因此在您重新启动解释器之前,无法在 Python 2 中导入该包或手动调用 site.main()
。这是因为在您的 site-packages
中创建了一个 .pth
文件,它告诉 Python 这是一个其他模块所在的名称空间。当解释器启动时,所有 .pth
文件都由 site.main()
加载,但由于你的文件是在解释器启动之后创建的,Python 不知道它。
In [1]: import pip
In [2]: pip.main(['install', 'bda.basen'])
Collecting bda.basen
Requirement already satisfied: setuptools in /usr/local/lib/python2.7/site-packages (from bda.basen)
Installing collected packages: bda.basen
Successfully installed bda.basen-1.1
Out[2]: 0
In [3]: import bda.basen
---------------------------------------------------------------------------
ImportError Traceback (most recent call last)
<ipython-input-3-e9d84961fc34> in <module>()
----> 1 import bda.basen
ImportError: No module named bda.basen
In [4]: import site
In [5]: site.main()
In [6]: import bda.basen
In [7]:
Python 3.3+ 的行为符合您的预期,因为它本机支持命名空间包并且不需要您调用 site.main()
.