如何通过setuptools安装python模块时包含配置文件?

时间:2017-10-14 20:26:44

标签: python pip setuptools

我编写了一个模块,用于机器人应用程序,它提供对机器人特定特征的访问,以及用于使用数据的python和c ++客户端。使用setuptools将python客户端捆绑到一个模块中。

(简化)目录结构如下所示:

<root of git repo>
├── config
│   ├── global
│   │   ├── <files common to all robots>
│   │   └── ...
│   ├── robot1
│   │   ├── camera_calibrations
│   │   │   ├── cam1.yml
│   │   │   ├── cam2.yml
│   │   │   ├── cam3.yml
│   │   └── vehicle_params.yaml
│   ├── robot2
│   │   └── ...
│   └── ...
├── cpp
│   └── <c++ client>
├── Makefile
├── python
│   └── <namespace>
│       ├── __init__.py
│       └── <module names>
│           ├── camera_calibrations.py
│           ├── ...
│           └── __init__.py
├── README.md
├── requirements.txt
└── setup.py

我的setup.py看起来像这样:

import os
import sys
from setuptools import setup, find_packages
from pip.req import parse_requirements
import shutil

# parse_requirements() returns generator of pip.req.InstallRequirement objects
REQUIREMENTS_FILE = os.path.join(os.path.dirname(__file__), 'requirements.txt')
dependencies = map(lambda ir: str(ir.req), parse_requirements(REQUIREMENTS_FILE, session='hack'))

CONFIG_FOLDER = os.path.join(os.path.dirname(__file__), 'config')
MODULE_DIR = os.path.join(sys.prefix, 'local', 'lib', 'python2.7', 'dist-packages', 'namespace', 'module_name')

def get_config_files():
    for root, _, files in os.walk(CONFIG_FOLDER):
        for filename in files:
            yield os.path.join(root, filename)

setup(
    name                 = "namespace.module_name",
    version              = "1.0.0",
    packages             = ['namespace.module_name'],
    package_dir          = {'': 'python'},
    #package_data         = {'': get_config_files()},
    install_requires     = dependencies,
    include_package_data = True,
    #data_files           = [(os.path.join(MODULE_DIR, 'config'), get_config_files())]
)

# Copy config files
## TODO: There's probably a better way to do this, but I've been working
## on it all morning soo....
CONFIG_DEST = os.path.join(MODULE_DIR, 'config')
if os.path.exists(CONFIG_DEST):
    shutil.rmtree(CONFIG_DEST)
shutil.copytree(CONFIG_FOLDER, CONFIG_DEST)

我希望python客户端始终能够找到相对于自身的配置(yml)文件。因此,如果您在repo中从源代码运行它,它会在本地文件夹中找到该副本。如果pip install编辑并作为包导入,则安装过程应将配置文件与.py文件一起复制,然后加载它。

我确定的黑客仅在用户以root身份安装时才有效,因此不是真正的解决方案。我还尝试了package_data中的data_filessetup选项,但这些选项也没有完全解决(你可以看到我尝试过的,我已经注释掉了)。

我还在python客户端中编写了这个实用程序函数,它显示了我的更多hackery:

def get_config_dir():
    # pylint: disable=global-statement
    global CONFIG_DIR
    if CONFIG_DIR is None:
        # HACK HACK HACK
        search = [
            os.path.join(CUR_DIR, 'config'),
            os.path.join(CUR_DIR, '..', '..', '..', 'config'),
            os.path.join('..', '..', '..', 'config'),
        ]
        for path in search:
            if os.path.exists(path):
                CONFIG_DIR = os.path.abspath(path)
                return CONFIG_DIR
        raise CouldNotFindConfigFolderException("Could not find config folder")
    return CONFIG_DIR

如果有人能指出我如何正确实现这一目标,我会很感激。

需要注意的是,配置文件与代码保持在一起并且不在系统的其他位置,这一点非常重要,因为配置可能会在版本控制下发生变化,因此更改必须与代码保持耦合。

0 个答案:

没有答案