You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python跨多层目录导入模块失败,寻求优雅解决方案

问题描述

项目文件结构

- scraper_backend
     - jobs
         - bronze
             - extract_bronze.py
- tests
    - jobs
        - bronze
             - extract_bronze_test.py

导入错误信息

运行测试时触发以下导入错误:

ImportError while importing test module 'D:\School\Academiejaar 3\Semester 2\internship2023-solarstreaming\tests\unit_tests\jobs\bronze\test_extract_bronze.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
C:\Users\david\AppData\Local\Programs\Python\Python310\lib\importlib\__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
tests\unit_tests\jobs\bronze\test_extract_bronze.py:4: in <module>
    from .....scraper_backend.jobs.bronze import extract_bronze
E   ImportError: attempted relative import with no known parent package
===================================================================================== short test summary info ===================================================================================== 
ERROR tests/unit_tests/jobs/bronze/test_extract_bronze.py
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
======================================================================================== 1 error in 0.13s ========================================================================================= 

测试文件导入代码

测试文件中的导入写法如下,两种方式都尝试过但报错:

from datetime import datetime
from .....scraper_backend.jobs.bronze import extract_bronze # 出错的相对导入
# 也试过绝对导入
# from scraper_backend.jobs.bronze import extract_bronze


def test_extract_energy_happy():
    energy_type = "solar"
    params = {
        "datetime": datetime.now(),
        "province": "Antwerp"
    }
    date_time = datetime.now()
    result = extract_bronze.extract_energy(energy_type, params, date_time)
    assert type(result) != str
    assert type(result) == float

已知现象

将测试文件移至tests根目录时可正常运行,推测问题源于目录嵌套过深。曾尝试用sys.path手动添加路径,但希望找到更优雅的解决方式。

优雅解决方案

1. 把项目转为可安装包(推荐)

在项目根目录创建pyproject.toml文件,将scraper_backend声明为可安装的Python包:

[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[project]
name = "scraper_backend"
version = "0.1.0"
packages = ["scraper_backend"]

然后在项目根目录执行命令,以开发模式安装包:

pip install -e .

安装完成后,测试文件里直接使用绝对导入即可:

from scraper_backend.jobs.bronze import extract_bronze

2. 为所有目录添加__init__.py

在scraper_backend、scraper_backend/jobs、scraper_backend/jobs/bronze、tests、tests/jobs、tests/jobs/bronze这些目录下,都创建一个空的__init__.py文件,将它们标记为Python包。

之后从项目根目录运行pytest,此时测试文件中的绝对导入就能正常生效。

3. 配置pytest根目录

在项目根目录创建pytest.ini文件,指定测试路径并将根目录加入Python路径:

[pytest]
testpaths = tests
pythonpath = .

配置完成后,运行pytest时会自动识别项目根目录,测试文件里的绝对导入from scraper_backend.jobs.bronze import extract_bronze就能正常工作。

内容的提问来源于stack exchange,提问作者david backx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 10:25:39