Python可以导入未安装的模块

时间:2017-11-30 15:22:37

标签: python python-3.x pip python-import

所以,我正在打包我编写的python脚本,它有一个子模块,我们称之为submodule。文件夹结构如下所示:

cool_script/
  setup.py
  cool_script.py
  submodule/
    __init__.py
    implementation.py

现在,经过多次pip install .pip install -e .来电,我的情况是submodule可以全局导入。无论我的系统在哪里,这都将始终有效:

$ python3
[...]
>>> import submodule
>>> submodule.__file__
'/home/me/fake/path/cool_script/submodule/__init__.py'

但我不知道为什么。

我再次卸载了我的包,并且pip在其索引中找不到子模块。在dist-package中也没有任何内容,我手动删除了仍然坐在那里的cool_script.egg-link

$ ls /usr/local/lib/python3.4/dist-packages | ack cool 
$ ls /usr/local/lib/python3.4/dist-packages | ack submodule
$ 

PYTHONPATH也是空的:

$ echo $PYTHONPATH

$

为什么Python知道submodule的位置?我该如何找到?

1 个答案:

答案 0 :(得分:3)

首先运行python -c "import site; print(site.getsitepackages())"。它会打印一个这样的列表:

['/XXX/something/site-packages']

通常此列表中有一个路径,它指向pip安装脚本的目录。如果您感到好奇,可以ls进入ls /XXX/something/site-packages/

更有趣的是,pip在您使用开发人员安装(a.k.a。pip install -e)时会在该目录中放置一个“链接”文件。 “链接”文件以原始项目命名,最后带有.egg-link扩展名。

因此,您可能在该目录中有一个cool_script.egg-link文件。如果您尝试将其打印出来,您应该会发现其内容列出了模块的原始文件系统位置。类似的东西:

$ cat /XXX/something/site-packages/cool_script.egg-link
/home/me/fake/path/cool_script/
.

这就是pip记录它在开发人员模式下安装了什么的方式,但不是Python实际上知道如何找到你的模块的方式(这本来太简单了,对吧?:-))。

Python不了解.egg-link个文件,但它会读取.pth目录中的所有site-packages个文件,以获取sys.path(*)的其他路径。因此,为了能够导入开发人员模式安装,pip将所有路径写入一个.pth文件,通常称为easy-install.pth(因为旧的easy-install工具实际上是先行者那种技术)。如果您打印出该文件,您将获得以开发人员模式安装的所有项目路径列表:

$ cat /XXX/something/site-packages/easy-install.pth
/home/me/fake/path/cool_script/
/home/me/another/project/

您可以检查确实easy-install.pth中列出的所有路径确实已添加到您的sys.path

(*)从技术上讲,读取那些.pth文件的Python部分是site模块,通常在启动时自动导入。但是,可以选择禁用site模块,例如使用python -S。在这种情况下,您会看到sys.path既不包含site-packages目录也不包含开发人员安装路径。