简体   繁体   English

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

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

Lets assume I have Python module in a directory and in the same directory I have a Python script that uses this module somehow.假设我在一个目录中有 Python 模块,在同一个目录中我有一个 Python 脚本以某种方式使用这个模块。

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

If I execute this file in a python environment where the module is not installed everything works fine as Python imports the module from it's source code.如果我在未安装模块的 python 环境中执行此文件,则一切正常,因为 Python 从其源代码导入模块。

The question is: if I install the module in this Python environment and continue executing the script the same way as before, will Python import the module from what was installed or from the source code?问题是:如果我在这个 Python 环境中安装模块并像以前一样继续执行脚本,Python 会从已安装的模块或源代码中导入模块吗? What is the hyerarchy Python follows to search for each import? Python 遵循什么层次结构来搜索每个导入?

Why does it matter: If I have a script repeatedly calling other Python scripts and modify the source code of the module during this execution, then there will be results that used the old version of the module and the new version as well, or even worse, executions may be missed if a bug is inserted into the module code.为什么重要:如果我有一个脚本重复调用其他 Python 脚本并在此执行期间修改模块的源代码,那么会出现使用旧版本和新版本的结果,甚至更糟,如果在模块代码中插入错误,则可能会错过执行。 But this would be solved if created a development env separated from the testing env.但是,如果创建一个与测试环境分开的开发环境,这将得到解决。

It seems to depend on sys.path它似乎取决于sys.path

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

When a module named spam is imported, the interpreter first searches for a built-in module with that name.当导入名为 spam 的模块时,解释器首先搜索具有该名称的内置模块。 If not found, it then searches for a file named spam.py in a list of directories given by the variable sys.path.如果没有找到,它会在变量 sys.path 给出的目录列表中搜索名为 spam.py 的文件。 sys.path is initialized from these locations: [edit: presumably in this order] sys.path 从这些位置初始化:[编辑:大概按此顺序]

The directory containing the input script (or the current directory when no file is specified).包含输入脚本的目录(或未指定文件时的当前目录)。

PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH). PYTHONPATH(目录名称列表,语法与 shell 变量 PATH 相同)。

The installation-dependent default.安装相关的默认值。

which goes on to say接着说

After initialization, Python programs can modify sys.path.初始化后Python程序可以修改sys.path。

which suggests to me that anything could in theory happen:-/这向我表明理论上任何事情都可能发生:-/

I guess module_stuff doesn't have the same name as a builtin so that rules out the first of these.我猜module_stuff与内置函数的名称不同,因此排除了第一个。

As you probably know, Python won't import the same module twice in a single run.您可能知道,Python 不会在一次运行中两次导入同一个模块。 Perhaps you can test it by making a small change to module/module_stuff and running again.也许您可以通过对module/module_stuff进行小改动并再次运行来测试它。

You can actually try this yourself: Lets build a module and install it, then modify it to see who takes preference:您实际上可以自己尝试:让我们构建一个模块并安装它,然后修改它以查看谁优先:

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

setup.py contains: setup.py 包含:

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

and myfun.py contains: myfun.py 包含:

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

Now we make a virtualenv and install it:现在我们创建一个 virtualenv 并安装它:

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

now we go to python and import现在我们从 go 到 python 并导入

from mymod.mymod.myfun import myfun 

myfun()
# Returns original Mod

Now we modify myfun.py wITHOUT installing it:现在我们修改 myfun.py 而不安装它:

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

and we go back to python:我们 go 回到 python:

from mymod.mymod.myfun import myfun 

myfun()
# returns Modified Mod

So looks like directories take precedence over modules, but give it a try!所以看起来目录优先于模块,但试一试!

(Note that if we change to a directory where mymod.myfun is not directly in our path it goes back to printing original mod) (请注意,如果我们更改到 mymod.myfun 不在我们的路径中的目录,它会返回打印原始 mod)

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

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