Python 在setup.py中安装期间动态复制程序包数据

Python 在setup.py中安装期间动态复制程序包数据,python,setuptools,Python,Setuptools,我有一个目录结构,如下所示: . ├── bitbucket-pipelines.yml ├── MANIFEST.in ├── pylintrc ├── setup.cfg ├── setup.py ├── src │   ├── bin │   │   ├── __init__.py │   │   └── project.py │   ├── __init__.py │   └── ml_project │   ├── configurations │   │   └──

我有一个目录结构,如下所示:

.
├── bitbucket-pipelines.yml
├── MANIFEST.in
├── pylintrc
├── setup.cfg
├── setup.py
├── src
│   ├── bin
│   │   ├── __init__.py
│   │   └── project.py
│   ├── __init__.py
│   └── ml_project
│       ├── configurations
│       │   └── precommit
│       ├── core
│       │   ├── command
│       │   │   ├── abs_command.py
│       │   │   ├── __init__.py
│       │   │   ├── no_command.py
│       │   │   ├── precommit.py
│       │   │   ├── project_utils.py
│       │   │   ├── setupsrc.py
│       │   │   └── setuptox.py
│       │   ├── configurations
│       │   │   └── precommit
│       │   └── __init__.py
│       └── __init__.py
└── tox.ini
"""Setup script."""

import io
import re
import os
import shutil
from setuptools import setup

PROJECT_NAME = "ml_project"
CONFIGURATIONS_DIR_NAME = "configurations"
FULL_CONFIG_DIR = os.path.join("src", PROJECT_NAME, CONFIGURATIONS_DIR_NAME)


def get_version() -> str:
    """Return the version stored in `ml_project/__init__.py:__version__`."""
    # see https://github.com/pallets/flask/blob/master/setup.py
    with io.open("src/ml_project/__init__.py", "rt", encoding="utf8") as init_file:
        return re.search(r'__version__ = "(.*?)"', init_file.read()).group(1)


def add_config_files_for_package(source_dir: str = None) -> None:
    if not source_dir:
        source_dir = os.path.dirname(os.path.abspath(__file__))
    config_files = {"precommit": [".gitlint", ".pre-commit-config.yaml"]}
    for config in config_files:
        config_dir = os.path.join(source_dir, FULL_CONFIG_DIR, config)
        for file in config_files[config]:
            shutil.copyfile(
                os.path.join(source_dir, file), os.path.join(config_dir, file)
            )


add_config_files_for_package()
setup(version=get_version())
include .gitlint
include .pre-commit-config.yaml
graft src/ml_project
当我为项目打包时,我的要求是基本上复制我的
ml\u项目
包的
configurations/precommit
文件夹中的文件
.gitlint
.pre-commit config.yaml
文件
configurations
只是一个普通目录,而不是Python包,因为它不包含
.py
文件

.gitlint
.pre-commit config.yaml
进行小的编辑,它们与
setup.py
处于同一级别

我的
setup.py
如下所示:

.
├── bitbucket-pipelines.yml
├── MANIFEST.in
├── pylintrc
├── setup.cfg
├── setup.py
├── src
│   ├── bin
│   │   ├── __init__.py
│   │   └── project.py
│   ├── __init__.py
│   └── ml_project
│       ├── configurations
│       │   └── precommit
│       ├── core
│       │   ├── command
│       │   │   ├── abs_command.py
│       │   │   ├── __init__.py
│       │   │   ├── no_command.py
│       │   │   ├── precommit.py
│       │   │   ├── project_utils.py
│       │   │   ├── setupsrc.py
│       │   │   └── setuptox.py
│       │   ├── configurations
│       │   │   └── precommit
│       │   └── __init__.py
│       └── __init__.py
└── tox.ini
"""Setup script."""

import io
import re
import os
import shutil
from setuptools import setup

PROJECT_NAME = "ml_project"
CONFIGURATIONS_DIR_NAME = "configurations"
FULL_CONFIG_DIR = os.path.join("src", PROJECT_NAME, CONFIGURATIONS_DIR_NAME)


def get_version() -> str:
    """Return the version stored in `ml_project/__init__.py:__version__`."""
    # see https://github.com/pallets/flask/blob/master/setup.py
    with io.open("src/ml_project/__init__.py", "rt", encoding="utf8") as init_file:
        return re.search(r'__version__ = "(.*?)"', init_file.read()).group(1)


def add_config_files_for_package(source_dir: str = None) -> None:
    if not source_dir:
        source_dir = os.path.dirname(os.path.abspath(__file__))
    config_files = {"precommit": [".gitlint", ".pre-commit-config.yaml"]}
    for config in config_files:
        config_dir = os.path.join(source_dir, FULL_CONFIG_DIR, config)
        for file in config_files[config]:
            shutil.copyfile(
                os.path.join(source_dir, file), os.path.join(config_dir, file)
            )


add_config_files_for_package()
setup(version=get_version())
include .gitlint
include .pre-commit-config.yaml
graft src/ml_project
因此,当我运行
python setup.py sdist
时,我使用
add\u config\u files\u for\u package
函数进行复制

我有一个
清单。在
文件中,如下所示:

.
├── bitbucket-pipelines.yml
├── MANIFEST.in
├── pylintrc
├── setup.cfg
├── setup.py
├── src
│   ├── bin
│   │   ├── __init__.py
│   │   └── project.py
│   ├── __init__.py
│   └── ml_project
│       ├── configurations
│       │   └── precommit
│       ├── core
│       │   ├── command
│       │   │   ├── abs_command.py
│       │   │   ├── __init__.py
│       │   │   ├── no_command.py
│       │   │   ├── precommit.py
│       │   │   ├── project_utils.py
│       │   │   ├── setupsrc.py
│       │   │   └── setuptox.py
│       │   ├── configurations
│       │   │   └── precommit
│       │   └── __init__.py
│       └── __init__.py
└── tox.ini
"""Setup script."""

import io
import re
import os
import shutil
from setuptools import setup

PROJECT_NAME = "ml_project"
CONFIGURATIONS_DIR_NAME = "configurations"
FULL_CONFIG_DIR = os.path.join("src", PROJECT_NAME, CONFIGURATIONS_DIR_NAME)


def get_version() -> str:
    """Return the version stored in `ml_project/__init__.py:__version__`."""
    # see https://github.com/pallets/flask/blob/master/setup.py
    with io.open("src/ml_project/__init__.py", "rt", encoding="utf8") as init_file:
        return re.search(r'__version__ = "(.*?)"', init_file.read()).group(1)


def add_config_files_for_package(source_dir: str = None) -> None:
    if not source_dir:
        source_dir = os.path.dirname(os.path.abspath(__file__))
    config_files = {"precommit": [".gitlint", ".pre-commit-config.yaml"]}
    for config in config_files:
        config_dir = os.path.join(source_dir, FULL_CONFIG_DIR, config)
        for file in config_files[config]:
            shutil.copyfile(
                os.path.join(source_dir, file), os.path.join(config_dir, file)
            )


add_config_files_for_package()
setup(version=get_version())
include .gitlint
include .pre-commit-config.yaml
graft src/ml_project
最后,下面是我的
设置.cfg

[options]
package_dir =
    =src
packages = find:
include_package_data = true
install_requires =
    click
    pre-commit
    pyyaml
    gitlint


[options.packages.find]
where = src

[options.entry_points]
console_scripts =
    project = bin.project:main

[options.extras_require]
tests =
    pytest
    pytest-mock
    pyfakefs
    pyyaml
    configparser
linting =
    pylint
testdocs =
    pydocstyle
pre-commit =
    pre-commit

[semantic_release]

version_variable = ml_project/__init__.py:__version__
这很好,但我的问题是:有没有更好、更标准的方法来做这些事情?比如一开始就不写函数


感谢您提前提供任何提示。

如评论中所述,最好将这些文件放在
src/ml_project/configurations/precommit
目录中,并在项目根目录下创建指向这些文件的符号链接。符号链接应该可以很好地使用git,但是一些平台(例如Windows)对它们没有很好的支持


或者,这些文件的副本可能只是构建过程中的另一个步骤(最终通过自定义setuptools命令),应该从Makefile(例如,或任何其他类似工具)和CI/CD工具链(在本例中为
bitbucket pipelines.yml
触发).

将它们永久地移动到
src/ml_项目/配置中
,无需每次都复制它们。在顶级目录中创建指向它们的符号链接。这引发了一个问题:为什么要这样做?这两个文件看起来不属于Python源代码发行版。否则,与@phd一样,我相信我会将文件放在
configurations
目录中,并在根目录中创建符号链接(假设您只在支持它们的平台上工作)。分发包时,我希望将它们复制到
configurations/precommit
中。这样我就不用再换两次了。此包用作命令行工具,用于将钩子安装到其他python包中。因此,这个包是一个整合预提交最佳实践的地方