如何在 Python setup.py 中递归添加包数据?

新手上路,请多包涵

我有一个新库,它必须包含许多小数据文件的子文件夹,我正试图将它们添加为包数据。想象一下我的图书馆是这样的:

  library
    - foo.py
    - bar.py
 data
   subfolderA
      subfolderA1
      subfolderA2
   subfolderB
      subfolderB1
      ...

我想通过 setup.py 添加所有子文件夹中的所有数据,但似乎我必须手动进入每个子文件夹(大约有 100 个)并添加一个 init .py 文件。此外,setup.py 会递归地找到这些文件,还是我需要在 setup.py 中手动添加所有这些文件,例如:

 package_data={
  'mypackage.data.folderA': ['*'],
  'mypackage.data.folderA.subfolderA1': ['*'],
  'mypackage.data.folderA.subfolderA2': ['*']
   },

我可以用脚本来做到这一点,但似乎非常痛苦。我怎样才能在 setup.py 中实现这个?

PS,这些文件夹的层次结构很重要,因为这是材料文件的数据库,我们希望在将它们以 GUI 形式呈现给用户时保留文件树,因此保持此文件结构完整对我们有利.

原文由 Dashing Adam Hughes 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 857
2 个回答
  1. 使用 Setuptools 而不是 distutils。
  2. 使用 数据文件 而不是包数据。这些不需要 __init__.py
  3. 使用标准 Python 代码生成文件和目录列表,而不是按字面意思编写:
    data_files = []
   directories = glob.glob('data/subfolder?/subfolder??/')
   for directory in directories:
       files = glob.glob(directory+'*')
       data_files.append((directory, files))
   # then pass data_files to setup()

原文由 Kevin 发布,翻译遵循 CC BY-SA 4.0 许可协议

glob 答案的问题在于它只能做这么多。即它不是完全递归的。 copy_tree 答案的问题是复制的文件将在卸载时留下。

正确的解决方案是递归解决方案,它可以让您在设置调用中设置 package_data 参数。

我写了这个小方法来做到这一点:

 import os

def package_files(directory):
    paths = []
    for (path, directories, filenames) in os.walk(directory):
        for filename in filenames:
            paths.append(os.path.join('..', path, filename))
    return paths

extra_files = package_files('path_to/extra_files_dir')

setup(
    ...
    packages = ['package_name'],
    package_data={'': extra_files},
    ....
)

您会注意到,当您执行 pip uninstall package_name 时,您会看到列出了您的其他文件(与包一起跟踪)。

原文由 Sandy Chapman 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题