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包之外,然后:

  1. data的位置通过configuration文件,命令行参数或
  2. 将位置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()