为什么Python`pip.main(['install',...])`给出了ImportError,但仅限于包含dot的包名?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么Python`pip.main(['install',...])`给出了ImportError,但仅限于包含dot的包名?相关的知识,希望对你有一定的参考价值。

当运行以下代码(Python 2.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.basenruamel.yaml),并且仅适用于那些。

我的问题:为什么?以及如何解决这个问题?

完整的可运行代码(将更新您的系统范围的包!)位于https://gist.github.com/marnix/2f4efc1154547103bcec3783e6015bfc

答案

bda是一个namespace package,因此不包括bda/__init__.py,因此在重新启动解释器或手动调用site.main()之前,无法在Python 2中导入该包。这是因为在.pth中创建了一个site-packages文件,该文件告诉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()

以上是关于为什么Python`pip.main(['install',...])`给出了ImportError,但仅限于包含dot的包名?的主要内容,如果未能解决你的问题,请参考以下文章

pycharm 安装第三方库报错:AttributeError: 'module' object has no attribute 'main'

pycharm 安装第三方库报错:AttributeError: 'module' object has no attribute 'main'

Python3,选择Python自动安装第三方库,从此跟pip说拜拜!!

Jupyter Notebook下安装第三方Python模块

'python svn'和'python pysvn'之间有什么区别?

Anaconda的新Pycharm项目需要每次都安装pip包