从父文件夹导入模块

1101 投票
32 回答
1481231 浏览
提问于 2025-04-15 11:05

我正在使用 Python 2.5。

这是我的文件夹结构:

ptdraft/
  nib.py
  simulations/
    life/
      life.py

(每个文件夹里我也有一个 __init__.py 文件,这里为了简洁没有列出)

我该如何从 life 模块中导入 nib 模块?我希望能在不修改 sys.path 的情况下做到这一点。

注意:当前运行的主模块在 ptdraft 文件夹里。

32 个回答

526

我之前也回答过一个关于从兄弟包导入的类似问题。你可以在这里查看。

不使用 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

在这个例子中,mainfolderptdraft。这样做的好处是你不会和其他模块名(来自 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!
756

你可以使用相对导入(Python 版本 >= 2.5):

from ... import nib

(Python 2.5 新特性) PEP 328: 绝对导入和相对导入

155

看起来这个问题和模块在父目录里什么的没有关系。

你需要把包含 ptdraft 的文件夹添加到 PYTHONPATH 里。

你提到 import nib 能正常工作,这可能意味着你把 ptdraft 本身(而不是它的父目录)添加到了 PYTHONPATH。

撰写回答