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

从TestPyPI安装的Python包目录结构与上传时不一致致报错

问题描述

我创建了name_generator_nicomp包并上传至TestPyPI。包内逻辑需要读取一个文本文件,本地开发时将文件放在独立文件夹中,运行正常。

在另一台机器通过以下命令安装该包:

python3 -m pip install --index-url https://test.pypi.org/simple/ name-generator-nicomp --upgrade

运行测试脚本时:

if __name__ == "__main__":
    from name_generator_nicomp.NameGenerator import NameGenerator
    nameGenerator = NameGenerator()

包内执行以下代码时失败:

with importlib.resources.open_text("src.data", self.noun_file) as my_file:

报错信息:

ModuleNotFoundError: No module named 'src'

构建生成的.gz包中存在src目录及内部的data目录,TestPyPI仓库也保留该结构,但安装到本地后,所有代码和数据文件都在同一文件夹,无其他目录层级。

我的pyproject.toml文件内容如下:

[project]
name = "name_generator_nicomp"
version = "0.0.2"
authors = [
  { name="xxx xxxxxx", email="xxx.com" },
]
description = "Some description."
readme = "README.md"
requires-python = ">=3.8"
classifiers = [
    "Programming Language :: Python :: 3",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
]

[project.urls]
Homepage = "https://github.com/nicomp42/name_generator"
Issues = "https://github.com/nicomp42/name_generator/issues"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

完整报错栈:

Traceback (most recent call last):
  File "C:\Users\nicholdw\eclipse-workspace\myNameGenerator\mainPackage\main.py", line 3, in <module>
    nameGenerator = NameGenerator()
  File "C:\Users\nicholdw\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\name_generator_nicomp\NameGenerator.py", line 36, in __init__
    self.prepare()
  File "C:\Users\nicholdw\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\name_generator_nicomp\NameGenerator.py", line 47, in prepare
    with importlib.resources.open_text("src.data", self.noun_file) as my_file:
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\lib\importlib\resources.py", line 82, in open_text
    open_binary(package, resource), encoding=encoding, errors=errors
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\lib\importlib\resources.py", line 43, in open_binary
    package = _common.get_package(package)
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\lib\importlib\_common.py", line 66, in get_package
    resolved = resolve(package)
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\lib\importlib\_common.py", line 57, in resolve
    return cand if isinstance(cand, types.ModuleType) else importlib.import_module(cand)
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\lib\importlib\__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 992, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1004, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'src'
解决方案

问题根源在于Hatchling构建时扁平化了src目录结构,同时资源文件的读取路径没有适配安装后的层级。

1. 调整包结构与构建配置

方式一:修改pyproject.toml指定源码目录

在pyproject.toml中添加Hatchling的构建配置,保留包的层级结构:

[tool.hatch.build]
sources = ["src"]

或者更精确地指定包路径:

[tool.hatch.build.targets.wheel]
packages = ["src/name_generator_nicomp"]

方式二:规范本地目录结构

将data目录作为包的子目录,确保结构如下:

src/
└── name_generator_nicomp/
    ├── __init__.py
    ├── NameGenerator.py
    └── data/
        ├── __init__.py  # 必须添加,让Python识别为模块
        └── [你的名词文件].txt

2. 修改资源读取代码

安装后src层级不再存在,需要将读取路径改为包内的相对路径:

# 替换原代码
with importlib.resources.open_text("name_generator_nicomp.data", self.noun_file) as my_file:

更推荐使用相对导入,避免硬编码包名:

from importlib.resources import open_text
from . import data

with open_text(data, self.noun_file) as my_file:

3. 重新构建上传

修改完成后,重新构建并上传至TestPyPI:

python -m build
python -m twine upload --repository testpypi dist/*

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 19:20:10