【问题标题】:Python can import a module that isn't installedPython 可以导入未安装的模块
【发布时间】:2017-11-30 15:22:37
【问题描述】:

所以,我正在尝试打包我编写的 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-packages 中也没有任何内容,我手动删除了仍然坐在那里的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 的位置?我怎样才能知道?

【问题讨论】:

  • 它是否安装在 virtualenv 中?是linux系统吗?
  • 这确实是一个linux系统,不,我在我的全局环境中做了这些实验。我知道那很愚蠢。我猜是吸取了教训。
  • 这听起来可能很愚蠢,但是您尝试过重新启动吗?也许它只是缓存在某个地方
  • 导入子模块时会发生什么?你有错误吗?
  • “我怎样才能找到答案?”我猜是sys.path。当前的工作目录也在那里,所以你确定这不仅仅是你从cool_script文件夹本身做的import submodule吗?

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


【解决方案1】:

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

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

这个列表中通常只有一个路径,它指向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/
.

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

Python 不知道.egg-link 文件,但它会读取site-packages 目录中的所有.pth 文件以获取sys.path (*) 的其他路径。因此,为了让 Python 能够导入开发人员模式安装,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 目录也不包含开发者安装路径。

【讨论】:

  • 就是这样,文件夹在easy-install.pth中列出。删除它解决了问题!感谢您的详尽解释。
猜你喜欢
  • 1970-01-01
  • 2017-08-03
  • 2018-06-13
  • 2020-12-26
  • 1970-01-01
  • 2016-09-08
  • 2017-07-08
  • 1970-01-01
  • 2018-01-21
相关资源
最近更新 更多