从父文件夹导入模块
我正在使用 Python 2.5。
这是我的文件夹结构:
ptdraft/
nib.py
simulations/
life/
life.py
(每个文件夹里我也有一个 __init__.py
文件,这里为了简洁没有列出)
我该如何从 life
模块中导入 nib
模块?我希望能在不修改 sys.path 的情况下做到这一点。
注意:当前运行的主模块在 ptdraft
文件夹里。
32 个回答
我之前也回答过一个关于从兄弟包导入的类似问题。你可以在这里查看。
不使用 sys.path
的解决方案
总结
- 把代码放到一个文件夹里(比如叫
packaged_stuff
) - 创建一个
pyproject.toml
文件(旧的替代方案是setup.py
) - 用
pip install -e <myproject_folder>
安装这个包,处于可编辑状态 - 使用
from packaged_stuff.modulename import function_name
来导入
设置
我假设文件夹结构和问题中的一样
.
└── ptdraft
├── __init__.py
├── nib.py
└── simulations
├── __init__.py
└── life
├── __init__.py
└── life.py
我把 .
称为根文件夹,在我的例子中,它位于 C:\tmp\test_imports
。
步骤
1) 在根文件夹添加一个 pyproject.toml
文件
pyproject.toml
文件的内容可以很简单
[project]
name = "ptdraft"
version = "0.1.0"
description = "My small project"
[build-system]
build-backend = "flit_core.buildapi"
requires = ["flit_core >=3.2,<4"]
基本上“任何”有效的 pyproject.toml
文件都可以用。这只是一个最小的工作示例,使用 flit 作为构建后端。
2) 使用虚拟环境
如果你对虚拟环境熟悉,可以激活一个,然后跳到下一步。 虚拟环境不是绝对 必需的,但从长远来看,它们会非常 有帮助(当你有多个项目时..)。最基本的步骤是(在根文件夹中运行)
- 创建虚拟环境
python -m venv venv
- 激活虚拟环境
. venv/bin/activate
(Linux)或./venv/Scripts/activate
(Windows)
- 停用虚拟环境
deactivate
(Linux)
想了解更多,可以在网上搜索“python virtualenv tutorial”或类似的内容。你可能只需要创建、激活和停用这些命令。
一旦你创建并激活了虚拟环境,你的控制台应该会显示虚拟环境的名称在括号中
PS C:\tmp\test_imports> python -m venv venv
PS C:\tmp\test_imports> .\venv\Scripts\activate
(venv) PS C:\tmp\test_imports>
3) 以可编辑状态安装你的项目
使用 pip
安装你的顶级包(这里是 ptdraft
)。关键是安装时使用 -e
标志。这样它就会以可编辑状态安装,所有对 .py 文件的修改都会自动包含在已安装的包中。注意,使用 pyproject.toml
的 -e
标志需要 pip 21.3 或更新版本。
在根目录下运行
pip install -e .
(注意点,它代表“当前目录”)
你也可以使用 pip freeze
查看它是否已安装
(venv) PS C:\tmp\test_imports> pip install -e .
Obtaining file:///home/user/projects/ptdraft
Installing build dependencies ... done
Checking if build backend supports build_editable ... done
Getting requirements to build editable ... done
Preparing editable metadata (pyproject.toml) ... done
....
Successfully built ptdraft
Installing collected packages: ptdraft
Successfully installed ptdraft-0.1.0
(venv) PS C:\tmp\test_imports> pip freeze
ptdraft==0.1.0
4) 在每个导入前加上 mainfolder
在这个例子中,mainfolder
是 ptdraft
。这样做的好处是你不会和其他模块名(来自 Python 标准库或第三方模块)发生名称冲突。
示例用法
nib.py
def function_from_nib():
print('I am the return value from function_from_nib!')
life.py
from ptdraft.nib import function_from_nib
if __name__ == '__main__':
function_from_nib()
运行 life.py
(venv) PS C:\tmp\test_imports> python .\ptdraft\simulations\life\life.py
I am the return value from function_from_nib!
看起来这个问题和模块在父目录里什么的没有关系。
你需要把包含 ptdraft
的文件夹添加到 PYTHONPATH 里。
你提到 import nib
能正常工作,这可能意味着你把 ptdraft
本身(而不是它的父目录)添加到了 PYTHONPATH。