繁体   English   中英

Python 模块导入的层次结构是什么?

[英]What is the hierarchy for Python module imports?

假设我在一个目录中有 Python 模块,在同一个目录中我有一个 Python 脚本以某种方式使用这个模块。

wdir
├── module
│   └── module_stuff
└── script.py

如果我在未安装模块的 python 环境中执行此文件,则一切正常,因为 Python 从其源代码导入模块。

问题是:如果我在这个 Python 环境中安装模块并像以前一样继续执行脚本,Python 会从已安装的模块或源代码中导入模块吗? Python 遵循什么层次结构来搜索每个导入?

为什么重要:如果我有一个脚本重复调用其他 Python 脚本并在此执行期间修改模块的源代码,那么会出现使用旧版本和新版本的结果,甚至更糟,如果在模块代码中插入错误,则可能会错过执行。 但是,如果创建一个与测试环境分开的开发环境,这将得到解决。

它似乎取决于sys.path

引用https://docs.python.org/3/tutorial/modules.html#the-module-search-path

当导入名为 spam 的模块时,解释器首先搜索具有该名称的内置模块。 如果没有找到,它会在变量 sys.path 给出的目录列表中搜索名为 spam.py 的文件。 sys.path 从这些位置初始化:[编辑:大概按此顺序]

包含输入脚本的目录(或未指定文件时的当前目录)。

PYTHONPATH(目录名称列表,语法与 shell 变量 PATH 相同)。

安装相关的默认值。

接着说

初始化后Python程序可以修改sys.path。

这向我表明理论上任何事情都可能发生:-/

我猜module_stuff与内置函数的名称不同,因此排除了第一个。

您可能知道,Python 不会在一次运行中两次导入同一个模块。 也许您可以通过对module/module_stuff进行小改动并再次运行来测试它。

您实际上可以自己尝试:让我们构建一个模块并安装它,然后修改它以查看谁优先:

mymod -- | setup.py | mymod --| myfun.py | __init__.py

setup.py 包含:

from setuptools import setup, find_packages
setup(
    name='mymod',
    version='1.0',
    packages=find_packages(),
)

myfun.py 包含:

def myfun():
    print('original Mod')

现在我们创建一个 virtualenv 并安装它:

virtualenv venv -p python3 
source venv/bin/activate
cd mymod
python setup.py install

现在我们从 go 到 python 并导入

from mymod.mymod.myfun import myfun 

myfun()
# Returns original Mod

现在我们修改 myfun.py 而不安装它:

def myfun():
    print('Modified Mod')

我们 go 回到 python:

from mymod.mymod.myfun import myfun 

myfun()
# returns Modified Mod

所以看起来目录优先于模块,但试一试!

(请注意,如果我们更改到 mymod.myfun 不在我们的路径中的目录,它会返回打印原始 mod)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM