基于pyproject.toml和setuptools安装测试文件的问题
迁移到pyproject.toml后测试依赖文件无法安装的解决办法
我正在将旧Python项目迁移到基于pyproject.toml的新体系,遇到测试所需文件无法安装的问题。使用pytest运行测试时需要指定的测试文件(.sdf、.urdf、.xml及.obj格式文件),但构建安装后这些文件并未被包含进去。我不想创建清单文件,之前查到过相关问题但情况已发生变化。
当前配置与项目结构
pyproject.toml配置
[tool.setuptools] package-data = {"my_pkg_name" = ["tests/*.sdf", "tests/*.urdf", "tests/*.xml", "tests/meshes/*.obj"]} [build-system] requires = ["setuptools>=43.0.0", "wheel"] build-backend = "setuptools.build_meta"
项目结构
. ├── LICENSE.txt ├── pyproject.toml ├── README.md ├── src │ ├── my_pkg_name │ │ ├── __init__.py └── tests ├── ant.xml ├── humanoid.xml ├── __init__.py ├── kuka_iiwa.urdf ├── meshes │ ├── link_0.obj │ ├── link_1.obj │ ├── link_2.obj │ ├── link_3.obj │ ├── link_4.obj │ ├── link_5.obj │ ├── link_6.obj │ └── link_7.obj └── test_transform.py
pyproject.toml中无特定的包发现相关设置。
问题原因
你用的package-data配置是绑定到my_pkg_name包的,但tests目录和src/my_pkg_name同级,不属于包内部目录。setuptools的package-data只处理包(即src/my_pkg_name下)的文件,所以这些测试文件不会被打包安装。
解决办法
办法1:用data_files配置(不用改项目结构)
修改pyproject.toml,添加data_files来指定测试文件的安装路径,把文件放到系统的共享目录下:
[tool.setuptools] data_files = [ # 把测试根目录的文件安装到share/my_pkg_name/tests ("share/my_pkg_name/tests", [ "tests/ant.xml", "tests/humanoid.xml", "tests/kuka_iiwa.urdf" ]), # 把meshes下的obj文件安装到对应子目录 ("share/my_pkg_name/tests/meshes", [ "tests/meshes/link_0.obj", "tests/meshes/link_1.obj", "tests/meshes/link_2.obj", "tests/meshes/link_3.obj", "tests/meshes/link_4.obj", "tests/meshes/link_5.obj", "tests/meshes/link_6.obj", "tests/meshes/link_7.obj" ]) ] [build-system] requires = ["setuptools>=43.0.0", "wheel"] build-backend = "setuptools.build_meta"
之后在测试代码里,用pkg_resources获取安装后的文件路径:
import pkg_resources ant_xml_path = pkg_resources.resource_filename('my_pkg_name', '../share/my_pkg_name/tests/ant.xml')
办法2:把tests目录移到包内(符合package-data设计)
调整项目结构,将tests目录放到src/my_pkg_name下面,变成包的子目录:
. ├── LICENSE.txt ├── pyproject.toml ├── README.md └── src └── my_pkg_name ├── __init__.py └── tests ├── ant.xml ├── humanoid.xml ├── __init__.py ├── kuka_iiwa.urdf ├── meshes │ ├── link_0.obj │ ├── ...(其他obj文件) └── test_transform.py
然后修改pyproject.toml的package-data路径(其实路径不用改,因为现在tests属于包内了):
[tool.setuptools] package-data = {"my_pkg_name" = ["tests/*.sdf", "tests/*.urdf", "tests/*.xml", "tests/meshes/*.obj"]} [build-system] requires = ["setuptools>=43.0.0", "wheel"] build-backend = "setuptools.build_meta"
测试时用importlib.resources访问文件:
from importlib.resources import files ant_xml_path = files('my_pkg_name.tests').joinpath('ant.xml')
办法3:开发模式安装(仅本地测试用)
如果只是本地开发测试,不需要构建正式包,直接用开发模式安装,这样pytest可以直接读取项目根目录的tests文件:
pip install -e .
内容的提问来源于stack exchange,提问作者LemonPi
相关产品推荐
相关产品推荐

