You need to enable JavaScript to run this app. pytest场景下目录名含连字符Python相对导入报错如何解决?
优惠活动
大模型
产品
解决方案
定价
更多

pytest场景下目录名含连字符Python相对导入报错如何解决?

根本原因

Python的包名必须是合法的标识符,仅支持字母、数字、下划线,且不能以数字开头,含连字符的目录无法被识别为标准Python包,因此相对导入机制会触发attempted relative import with no known parent package报错。


解决方案1:动态加载配置文件(无需调整运行参数)

直接通过文件路径加载同目录下的settings.py,绕过包导入规则,代码示例:

import importlib.util
from pathlib import Path

# 加载同目录下的settings.py
spec = importlib.util.spec_from_file_location("settings", Path(__file__).parent / "settings.py")
settings = importlib.util.module_from_spec(spec)
spec.loader.exec_module(settings)

# 把配置变量导入当前命名空间,等效于from settings import *
globals().update(vars(settings))


def test_port(host):
    assert host.socket(f"tcp://127.0.0.1:{ PORT }").is_listening

解决方案2:将当前测试目录加入Python导入路径

在测试文件开头先把当前文件所在目录加入sys.path,之后直接导入settings即可,无需使用相对导入:

import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.resolve()))

from settings import *


def test_port(host):
    assert host.socket(f"tcp://127.0.0.1:{ PORT }").is_listening

如果要全局生效,无需修改每个测试文件,可以在pytest配置文件pytest.ini中添加如下配置:

[pytest]
pythonpath = .

解决方案3:使用pytest conftest共享配置(最推荐)

pytest会自动加载测试目录下的conftest.py文件,不受目录名格式限制,你可以把配置都放到conftest中,不需要任何导入操作:

  1. 在测试目录下新建conftest.py,写入配置:
import pytest

# 用fixture方式共享配置
@pytest.fixture(scope="session")
def app_port():
    return 8080

# 也可以直接定义全局变量
PORT = 8080
  1. 测试用例直接引用即可:
# 用法1:直接使用fixture
def test_port(host, app_port):
    assert host.socket(f"tcp://127.0.0.1:{ app_port }").is_listening

# 用法2:直接从conftest导入变量
from conftest import PORT
def test_port(host):
    assert host.socket(f"tcp://127.0.0.1:{ PORT }").is_listening

内容的提问来源于stack exchange,提问作者George Shuklin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 05:09:02