setuptools:打包数据文件夹的位置
我使用setuptools来分发我的python包。 现在我需要分发额外的数据文件。
从我从setuptools文档中得到的信息,我需要将我的数据文件放在软件包目录中。 不过,我宁愿将我的数据文件放在根目录的子目录中。
我想避免的是:
/ #root |- src/ | |- mypackage/ | | |- data/ | | | |- resource1 | | | |- [...] | | |- __init__.py | | |- [...] |- setup.py
我想代之以:
/ #root |- data/ | |- resource1 | |- [...] |- src/ | |- mypackage/ | | |- __init__.py | | |- [...] |- setup.py
如果有这么多的子目录,我觉得不舒服。 我无法find一个理由,为什么我/有/将文件放在包目录中。 使用这么多的嵌套子目录恕我直言,这也是麻烦的。 还是有什么好的理由来certificate这个限制?
选项1:作为包数据安装
将数据文件放在Python包的根目录下的主要优点是,它可以让您避免担心文件在用户的系统(可能是Windows,Mac,Linux,某个移动平台或鸡蛋中)上的位置。 无论安装在哪里或如何安装,您都可以find与您的Python软件包根目录相关的目录data
。
例如,如果我有这样的项目布局:
project/ foo/ __init__.py data/ resource1/ foo.txt
您可以在__init__.py
添加一个函数来查找数据文件的绝对path:
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
在项目作为一个鸡蛋安装后, data
的path将改变,但代码不需要改变:
/Users/pat/virtenv/foo/lib/python2.6/site-packages/foo-0.0.0-py2.6.egg/foo/data/resource1/foo.txt
选项2:安装到固定位置
另一种方法是将您的数据放在Python包之外,然后:
- 让
data
的位置通过configuration文件,命令行参数或 - 将位置embedded到您的Python代码中。
如果您计划分发您的项目,这是不太可取的。 如果您真的想这样做,您可以通过传递元组列表来指定每个文件组的目的地,将data
安装到目标系统上的任意位置:
from setuptools import setup setup( ... data_files=[ ('/var/data1', ['data/foo.txt']), ('/var/data2', ['data/bar.txt']) ] )
更新 :recursiongrep 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']}
我想我find了一个很好的折衷办法,可以让你维持以下结构:
/ #root |- data/ | |- resource1 | |- [...] |- src/ | |- mypackage/ | | |- __init__.py | | |- [...] |- setup.py
您应该将数据安装为package_data,以避免在samplebias answer中描述的问题,但为了维护您应该添加到setup.py的文件结构:
try: os.symlink('../../data', 'src/mypackage/data' setup( ... package_data = {'mypackage': ['data/*']} ... ) finally: os.unlink('src/mypackage/data')
这样我们就可以“及时”地创build适当的结构,并组织起源树。
要在你的代码中访问这样的数据文件,你只需要使用:
data = resource_filename(Requirement.parse("main_package"), 'mypackage/data')
我仍然不喜欢在代码中指定'mypackage',因为数据本来可以与这个模块无关,但我想它是一个很好的折衷。
我使用setuptools来创build本地操作系统软件包,如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/
。
我认为你基本上可以把任何东西作为参数* data_files *给setup() 。