我使用setuptools来分发我的python包。现在我需要分发额外的数据文件。
从我从setuptools文档中收集到的内容,我需要将我的数据文件放在包目录中。但是,我宁愿将我的数据文件放在根目录的子目录中。
我想避免的事情:
/ #root
|- src/
| |- mypackage/
| | |- data/
| | | |- resource1
| | | |- [...]
| | |- __init__.py
| | |- [...]
|- setup.py
我想要的是:
/ #root
|- data/
| |- resource1
| |- [...]
|- src/
| |- mypackage/
| | |- __init__.py
| | |- [...]
|- setup.py
如果它不是必需的话,我对拥有这么多子目录感到不舒服。我找不到原因,为什么我/ /将文件放在包目录中。使用如此多的嵌套子目录恕我直言也很麻烦。或者有任何理由可以证明这种限制吗?
答案 0 :(得分:97)
选项1:作为包数据安装
将数据文件放在Python包的根目录中的主要优点
是它可以让你避免担心文件将存在于用户的位置
系统,可能是Windows,Mac,Linux,某些移动平台,或者是一个Egg。您可以
总是找到相对于Python包root的目录data
,无论它在何处或如何安装。
例如,如果我有这样的项目布局:
project/
foo/
__init__.py
data/
resource1/
foo.txt
您可以向__init__.py
添加一个函数来定位数据的绝对路径
文件:
import os
_ROOT = os.path.abspath(os.path.dirname(__file__))
def get_data(path):
return os.path.join(_ROOT, 'data', path)
print get_data('resource1/foo.txt')
输出:
/Users/pat/project/foo/data/resource1/foo.txt
将项目作为Egg安装后,data
的路径将发生变化,但代码无需更改:
/Users/pat/virtenv/foo/lib/python2.6/site-packages/foo-0.0.0-py2.6.egg/foo/data/resource1/foo.txt
选项2:安装到固定位置
另一种方法是将数据放在Python包之外 之一:
data
的位置,
命令行参数或如果您计划分发项目,这远远不太理想。如果确实想要这样做,您可以通过传入元组列表为每组文件指定目标,在目标系统上的任何位置安装data
:
from setuptools import setup
setup(
...
data_files=[
('/var/data1', ['data/foo.txt']),
('/var/data2', ['data/bar.txt'])
]
)
已更新:递归grep Python文件的shell函数示例:
atlas% function grep_py { find . -name '*.py' -exec grep -Hn $* {} \; }
atlas% grep_py ": \["
./setup.py:9: package_data={'foo': ['data/resource1/foo.txt']}
答案 1 :(得分:8)
我认为我找到了一个很好的妥协方案,可以让你保留以下结构:
/ #root
|- data/
| |- resource1
| |- [...]
|- src/
| |- mypackage/
| | |- __init__.py
| | |- [...]
|- setup.py
您应该将数据安装为package_data,以避免samplebias回答中描述的问题,但为了保留您应该添加到setup.py的文件结构:
try:
os.symlink('../../data', 'src/mypackage/data')
setup(
...
package_data = {'mypackage': ['data/*']}
...
)
finally:
os.unlink('src/mypackage/data')
通过这种方式,我们可以及时创建适当的结构"并保持我们的源代码树的组织。
要在您的代码中访问此类数据文件,您只需简单地'使用方法:
data = resource_filename(Requirement.parse("main_package"), 'mypackage/data')
我仍然不想指定“我的包装”#39;在代码中,由于数据可能与此模块无关,但我认为这是一个很好的妥协。
答案 2 :(得分:-1)
我使用setuptools创建本地操作系统包,如RPM和DEB。我使用的项目布局是。
<project>/
lib/ -> .../lib/pythonX/site-packages/
bin/ -> .../bin/
etc/ -> /etc/
doc/
man/ -> .../man/man1/
share/ -> .../share/doc/<project>/
我的setup.py
文件执行上面指定的相应映射。我觉得这个布局非常适合python。他们生成的包是可重定位的,但默认情况下会在/usr/local/
下。
答案 3 :(得分:-3)
我认为您基本可以将任何内容作为参数* data_files *提供给 setup()。