1

背景

我有一个我正在处理的包,我也安装到site-packages. (我已经安装了我自己的包pip

问题

Python 如何知道从“本地”代码(我正在处理的代码)导入,而不是从导入site-packages我问是因为我想更好地理解并且我担心我可能会以某种方式从site-packages我真的想使用我自己的(最新)代码时导入代码

令我困惑的是,这在我们如何编写导入时并没有更清楚。在我看来,程序员不知道她是在导入自己的代码还是从site-packages. 我在这里错过了什么吗?


我的一个想法是使用相对进口,但如果我理解他们一般不推荐


我正在使用 Python 3.8.5

4

3 回答 3

3

Python 的import机制(通常称为导入机制)基于Finders 和 Loaders。当您使用 import 语句导入模块时,一系列查找器会尝试查找您正在导入的模块。您可以查看按顺序触发的所有查找器的列表:

>>> import sys
>>> sys.meta_path
[<class '_frozen_importlib.BuiltinImporter'>,
 <class '_frozen_importlib.FrozenImporter'>,
 <class '_frozen_importlib_external.PathFinder'>]

如果没有一个查找器能够解析该模块,则ModuleNotFoundError引发。

BuiltinImporter解析预加载到解释器中的 sys、time、gc 等模块。FrozenImporter解决冻结的模块。PathFinder通过遍历中的路径来解析模块sys.path

打印sys.path显示您的当前目录是第一个条目,因此首先搜索匹配项。

这是一个简单的序列,您可以使用它来推断导入将从何处发生:

  1. 是内置模块的模块部分。示例:import sys。即使你的当前目录中有一个名为 sys.py 的文件,由于BuiltinImporter首先被调用,它会解析内置的 sys 模块。
  2. 模块是否存在于您的当前目录中,因为这是sys.path.
  3. 该模块是作为核心 python 或站点包的一部分提供的吗?

由 PathFinder 导入的模块(存在于 sys.path 中的模块)将具有__path__一个属性,您可以检查它的位置。

也可以重新排序 sys.meta_path 中的查找器,甚至添加您自己的自定义查找器和加载器,让您完全控制和创造性地修改默认机器。可以注册自定义查找器和加载器以查找系统中其他地方的模块,甚至可以从外部系统动态查找模块。

于 2021-02-20T10:55:09.560 回答
0

如果要将包符号链接为开发安装,请使用:

pip install --no-dependencies --editable .

或者:

python setup.py develop

无需修改 sys.path

您当前的文件夹将符号链接到站点包。因此,如果你的包名是foo,你可以用

from foo import bar
# or
import foo
foo.bar.do_something()
于 2021-02-20T10:19:04.757 回答
0

我会考虑创建一个没有安装pip包的虚拟环境。这是您可以确定您使用的是本地版本!

如果您对从哪里导入包感到困惑,可以使用.__path__ 来查找。

import my_package
print(my_pacakge.__path__)
于 2021-02-20T10:20:24.330 回答