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

2024-09-22 16:34:25 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

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

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

我可以用剧本来做,但看起来很痛苦。如何在setup.py中实现此目标?

PS,这些文件夹的层次结构很重要,因为这是一个材料文件的数据库,我们希望在图形用户界面中显示这些文件时保留文件树,因此保持此文件结构的完整性将对我们有利。


Tags: 文件数据py文件夹data图书馆数据文件setup
3条回答

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

正确的解决方案是递归的,它允许您在setup调用中设置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时,你会看到你的附加文件被列出(与包一起跟踪)。

如果在获取setup.py代码时没有任何问题,请使用distutils.dir_util.copy_tree
整个问题是如何从中排除文件。
下面是一些代码:

import os.path
from distutils import dir_util
from distutils import sysconfig
from distutils.core import setup

__packagename__ = 'x' 
setup(
    name = __packagename__,
    packages = [__packagename__],
)

destination_path = sysconfig.get_python_lib()
package_path = os.path.join(destination_path, __packagename__)

dir_util.copy_tree(__packagename__, package_path, update=1, preserve_mode=0)

一些注释

  • 此代码递归地将源代码复制到目标路径中。
  • 您可以使用相同的setup(...),但可以使用copy_tree()将所需目录扩展到安装路径中。
  • distutil安装的默认路径可以在它的API中找到。
  • 有关distutils的copy_tree()模块的更多信息,请参见here
    1. 使用Setuptools而不是distutils。
    2. 使用data files而不是包数据。这些不需要__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()
      

    相关问题 更多 >