我编写了一个模块,用于机器人应用程序,它提供对机器人特定特征的访问,以及用于使用数据的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_files
和setup
选项,但这些选项也没有完全解决(你可以看到我尝试过的,我已经注释掉了)。
我还在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
如果有人能指出我如何正确实现这一目标,我会很感激。
需要注意的是,配置文件与代码保持在一起并且不在系统的其他位置,这一点非常重要,因为配置可能会在版本控制下发生变化,因此更改必须与代码保持耦合。