Python 如何知道从我正在处理的代码中导入,而不是从站点包中导入?
How does Python know to import from the code i'm working on, rather than importing from site-packages?
背景
我有一个正在处理的软件包,我也已将其安装到 site-packages
。 (我使用 pip
安装了自己的包)
问题
Python 如何知道从“本地”代码(我正在处理的代码)导入,而不是从 site-packages
导入? 我问是因为 我想更好地理解并且我担心当我真的想使用我自己的(最新)代码时,我可能会以某种方式从 site-packages
导入代码
让我感到困惑的是,我们如何编写导入并不清楚。在我看来,程序员不知道她是在导入自己的代码还是从 site-packages
导入。我在这里遗漏了什么吗?
我曾想过使用相对导入,但据我所知,一般不推荐使用它们
我正在使用 Python 3.8.5
如果你想将你的包符号链接为开发安装,请使用:
pip install --no-dependencies --editable .
或:
python setup.py develop
无需修改sys.path
您当前的文件夹将被符号链接到站点包。因此,如果
你的包名是foo
,你可以用
导入模块
from foo import bar
# or
import foo
foo.bar.do_something()
我会考虑创建一个 virtual enviroment, 没有安装 pip 包。这是您可以确定您使用的是本地版本!
如果您对从哪里导入包感到困惑,可以使用 .__path__
找出答案。
import my_package
print(my_pacakge.__path__)
Python的import
机制(俗称进口机械)是基于Finders and Loaders的。当您使用 import 语句导入模块时,一系列查找器会尝试查找您正在导入的模块。您可以看到按以下顺序触发的所有查找器的列表:
>>> import sys
>>> sys.meta_path
[<class '_frozen_importlib.BuiltinImporter'>,
<class '_frozen_importlib.FrozenImporter'>,
<class '_frozen_importlib_external.PathFinder'>]
如果 none 的发现者能够解析模块,则 ModuleNotFoundError
被提出。
BuiltinImporter
解析预加载到解释器中的模块,如 sys、time、gc 等。 FrozenImporter
解决冻结模块。 PathFinder
通过 sys.path
.
中的路径解析模块
正在打印 sys.path
显示您的当前目录是第一个条目,因此首先搜索匹配项。
这是一个简单的序列,您可以使用它来推断导入将从哪里发生:
- 是内置模块的模块部分。示例:
import sys
。即使你的当前目录中有一个名为 sys.py 的文件,由于 BuiltinImporter
首先被调用,它会解析内置的 sys 模块。
- 模块是否存在于您的当前目录中,因为这是
sys.path
中的第一个条目。
- 该模块是否作为核心 python 或站点包的一部分提供。
由 PathFinder 导入的模块(存在于 sys.path 中的模块)将具有 __path__
作为属性,您可以检查它的位置。
也可以重新排序 sys.meta_path 中的查找器,甚至添加您自己的自定义查找器和加载器,让您完全控制和创造性地修改默认机器。可以注册自定义查找器和加载器以查找系统中其他地方的模块,甚至可以动态地从外部系统中查找。
背景
我有一个正在处理的软件包,我也已将其安装到 site-packages
。 (我使用 pip
安装了自己的包)
问题
Python 如何知道从“本地”代码(我正在处理的代码)导入,而不是从 site-packages
导入? 我问是因为 我想更好地理解并且我担心当我真的想使用我自己的(最新)代码时,我可能会以某种方式从 site-packages
导入代码
让我感到困惑的是,我们如何编写导入并不清楚。在我看来,程序员不知道她是在导入自己的代码还是从 site-packages
导入。我在这里遗漏了什么吗?
我曾想过使用相对导入,但据我所知,一般不推荐使用它们
我正在使用 Python 3.8.5
如果你想将你的包符号链接为开发安装,请使用:
pip install --no-dependencies --editable .
或:
python setup.py develop
无需修改sys.path
您当前的文件夹将被符号链接到站点包。因此,如果
你的包名是foo
,你可以用
from foo import bar
# or
import foo
foo.bar.do_something()
我会考虑创建一个 virtual enviroment, 没有安装 pip 包。这是您可以确定您使用的是本地版本!
如果您对从哪里导入包感到困惑,可以使用 .__path__
找出答案。
import my_package
print(my_pacakge.__path__)
Python的import
机制(俗称进口机械)是基于Finders and Loaders的。当您使用 import 语句导入模块时,一系列查找器会尝试查找您正在导入的模块。您可以看到按以下顺序触发的所有查找器的列表:
>>> import sys
>>> sys.meta_path
[<class '_frozen_importlib.BuiltinImporter'>,
<class '_frozen_importlib.FrozenImporter'>,
<class '_frozen_importlib_external.PathFinder'>]
如果 none 的发现者能够解析模块,则 ModuleNotFoundError
被提出。
BuiltinImporter
解析预加载到解释器中的模块,如 sys、time、gc 等。 FrozenImporter
解决冻结模块。 PathFinder
通过 sys.path
.
正在打印 sys.path
显示您的当前目录是第一个条目,因此首先搜索匹配项。
这是一个简单的序列,您可以使用它来推断导入将从哪里发生:
- 是内置模块的模块部分。示例:
import sys
。即使你的当前目录中有一个名为 sys.py 的文件,由于BuiltinImporter
首先被调用,它会解析内置的 sys 模块。 - 模块是否存在于您的当前目录中,因为这是
sys.path
中的第一个条目。 - 该模块是否作为核心 python 或站点包的一部分提供。
由 PathFinder 导入的模块(存在于 sys.path 中的模块)将具有 __path__
作为属性,您可以检查它的位置。
也可以重新排序 sys.meta_path 中的查找器,甚至添加您自己的自定义查找器和加载器,让您完全控制和创造性地修改默认机器。可以注册自定义查找器和加载器以查找系统中其他地方的模块,甚至可以动态地从外部系统中查找。