必须用绝对导入:直接运行脚本时相对导入会因无父包而报错;用 python -m 运行包内模块才支持相对导入,且需满足包结构和执行路径要求;测试文件默认不被视为包成员,应统一使用绝对导入并确保项目在 sys.path 中。

直接运行脚本时,必须用绝对导入
当你写完 scripts/runner.py,然后在终端敲 python scripts/runner.py,里面如果写了 from ..utils import db,一定会报错:ImportError: attempted relative import with no known parent package。这是因为 Python 此时把 runner.py 当作顶层脚本(__name__ == '__main__'),它没有 __package__ 属性,相对导入根本无从解析。
解决方法只有一条:全部改用绝对导入,例如 from myproject.utils import db,并确保 myproject 所在目录在 sys.path 中。常用手段包括:
- 项目根目录下执行
pip install -e .(前提是setup.py或pyproject.toml配置正确) - 临时插入路径:
sys.path.insert(0, "/path/to/myproject") - 设置环境变量:
PYTHONPATH=/path/to/myproject
用 python -m 运行包内模块时,相对导入才可能生效
相对导入不是“不能用”,而是有严格前提:模块必须被当作包的一部分加载,且当前工作目录不能是包内部。比如结构是 myproject/pkg/main.py,想在 main.py 里写 from .helpers import load_config,必须满足:
-
main.py所在的pkg/目录下有__init__.py - 你在
myproject/目录下执行:python -m pkg.main(不是python pkg/main.py) -
main.py的__name__是pkg.main,不是__main__
一旦路径或执行方式偏差一点,比如误在 pkg/ 目录下执行 python -m main,就会触发 ValueError: Attempted relative import in non-package。
测试文件(test_*.py)默认不被视为包成员
pytest 或 unittest 运行 tests/test_main.py 时,通常不会把它识别为 myproject.tests 的一部分——即使你加了 __init__.py。结果就是,里面写的 from ..src import core 会直接失败。
调用 Cutout.Pro 视觉处理 API 进行背景移除、人像抠图和照片增强,支持文件上传与图片 URL 输入。
这不是 pytest 的 bug,而是它的默认行为:不自动推导包结构。应对方式很实际:
- 测试文件统一用绝对导入:
from myproject.src import core - 确保
myproject在sys.path中(推荐pip install -e .) - 避免在
test_*.py里写相对导入,哪怕结构看起来“应该可以”
团队协作和 CI 环境里,绝对导入是唯一安全选择
不同人本地的工作目录、IDE 的运行配置、CI 脚本的 cd 路径,都会影响 python -m 是否能成功解析相对路径。一个在你机器上跑通的 from .. import config,很可能在 GitHub Actions 里因工作目录不同而崩掉。
绝对导入虽然要写更长的包名,但它把依赖关系显式暴露出来,而且不受执行上下文干扰。尤其当项目引入新成员或接入黑盒测试框架时,这点差异会直接决定调试时间是几分钟还是几小时。
真正容易被忽略的点是:__init__.py 存在 ≠ 包就自动可导入;import myproject 成功 ≠ from myproject.pkg import mod 就一定行——关键永远是 myproject 这个名字是否在 sys.path 的某个位置下真实可查。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










