Python可以导入未安装的模块

iFr*_*cht 6 python pip python-import python-3.x

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

cool_script/
  setup.py
  cool_script.py
  submodule/
    __init__.py
    implementation.py
Run Code Online (Sandbox Code Playgroud)

现在,许多经过pip install .pip install -e .电话,我有那里的情况submodule可以在全球范围内导入.无论我的系统在哪里,这都将始终有效:

$ python3
[...]
>>> import submodule
>>> submodule.__file__
'/home/me/fake/path/cool_script/submodule/__init__.py'
Run Code Online (Sandbox Code Playgroud)

但我不知道为什么.

我做的包再次被卸载,并且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
$ 
Run Code Online (Sandbox Code Playgroud)

PYTHONPATH也是空的:

$ echo $PYTHONPATH

$
Run Code Online (Sandbox Code Playgroud)

为什么Python知道它的位置submodule?我该怎么知道?

Ant*_* P. 4

第一次运行python -c "import site; print(site.getsitepackages())"。它将打印一个如下列表:

['/XXX/something/site-packages']
Run Code Online (Sandbox Code Playgroud)

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

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

所以您可能在该目录中有一个cool_script.egg-link文件。如果您尝试打印它,您应该会发现它的内容列出了模块的原始文件系统位置。就像是:

$ cat /XXX/something/site-packages/cool_script.egg-link
/home/me/fake/path/cool_script/
.
Run Code Online (Sandbox Code Playgroud)

这就是pip它在开发者模式下安装某些东西的记录方式,但这并不是 Python 实际上知道如何找到你的模块的方式(这太简单了,对吧?:-))。

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

$ cat /XXX/something/site-packages/easy-install.pth
/home/me/fake/path/cool_script/
/home/me/another/project/
Run Code Online (Sandbox Code Playgroud)

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

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