当包在子目录中时,包括来自顶层的包数据 Python

Including Package Data Python from Top-level when Package is in Subdirectory

我正在尝试将一系列配置文件与一些源代码打包在一起。我有一个这样的目录结构(由于团队的性质,我无法更改)

.
├── configs
│   ├── machines
│   ├── scope
├── esm_tools
│   ├── __init__.py
├── README.rst
├── setup.cfg
├── setup.py

61 directories, 45 files (Truncated)

根据我在这里的理解 (https://docs.python.org/3/distutils/setupscript.html#installing-package-data),我可以将一些部分添加到设置调用中:


setup(
    # ... other stuff
    include_package_data=True,
    name="esm_tools",
    packages=["configs", "esm_tools"],
    package_dir={"configs": "configs", "esm_tools": "esm_tools"},
    package_data={'configs': ['*']},
    version="4.1.5",
    zip_safe=False,
)

但是,我无法通过以下方式访问包数据:

In [1]: import pkg_resources                                                                                                                                                                                                                                                                       

In [2]: pkg_resources.resource_listdir("esm_tools", "config")                                                                                                                                                                                                                                      
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
<ipython-input-2-f0f255c14df6> in <module>
----> 1 pkg_resources.resource_listdir("esm_tools", "config")

/global/AWIsoft/miniconda/4.7.12/lib/python3.7/site-packages/pkg_resources/__init__.py in resource_listdir(self, package_or_requirement, resource_name)
   1161         """List the contents of the named resource directory"""
   1162         return get_provider(package_or_requirement).resource_listdir(
-> 1163             resource_name
   1164         )
   1165 

/global/AWIsoft/miniconda/4.7.12/lib/python3.7/site-packages/pkg_resources/__init__.py in resource_listdir(self, resource_name)
   1439 
   1440     def resource_listdir(self, resource_name):
-> 1441         return self._listdir(self._fn(self.module_path, resource_name))
   1442 
   1443     def metadata_listdir(self, name):

/global/AWIsoft/miniconda/4.7.12/lib/python3.7/site-packages/pkg_resources/__init__.py in _listdir(self, path)
   1608 
   1609     def _listdir(self, path):
-> 1610         return os.listdir(path)
   1611 
   1612     def get_resource_stream(self, manager, resource_name):

FileNotFoundError: [Errno 2] No such file or directory: '/home/ollie/pgierz/dev/esm_tools/esm_tools/esm_tools/config'

任何帮助将不胜感激,我不确定我做错了什么...

根据你的调用 pkg_resources.resource_listdir("esm_tools", "config"),我假设你想在安装包中将 configs 重新映射到 esm_tools.config

site-packages
├── esm_tools
│   ├── __init__.py
│   ├── config
│   │   ├── machines
│   │   ├── scope

这意味着您必须执行以下操作:

  1. 告诉setuptools包含一个子包esm_tools.config(即使它在源代码库中并不真正存在并且在技术上是一个命名空间,我们将通过进一步配置来构造它)
  2. 告诉 setuptools 新的 esm_tools.config 包的源代码位于何处(这也是告诉 setuptools 在 dist 中包含什么的必要措施。包本身不会提供任何 Python 来源,因为 Python 文件位于 configs).
  3. 告诉 setuptools 从正确的路径包含 esm_tools.config 的包数据。

示例:

setup(
    ...,
    packages=['esm_tools', 'esm_tools.config'],           # 1
    package_dir={'esm_tools.config': 'configs'},          # 2
    package_data={'esm_tools.config': ['../configs/*']},  # 3
)

请注意,这不适用于可编辑安装(无论是通过 pip install --editable . 还是 python setup.py develop),因此您将不得不使用符号链接或 [=26 构建或多或少丑陋的本地解决方法=] 文件或其他任何东西。 wheel dist(通过 python setup.py bdist_wheelpip wheel 构建)将开箱即用,对于源 dist,您必须通过 MANIFEST.in 包含 configs 目录作为 package_data 不会在 sdist 时间被读取:

# MANIFEST.in
...
graft configs