setuptools:包数据文件夹位置

时间:2010-12-23 13:25:48

标签: python setuptools

我使用setuptools来分发我的python包。现在我需要分发额外的数据文件。

从我从setuptools文档中收集到的内容,我需要将我的数据文件放在包目录中。但是,我宁愿将我的数据文件放在根目录的子目录中。

我想避免的事情:

/ #root
|- src/
|  |- mypackage/
|  |  |- data/
|  |  |  |- resource1
|  |  |  |- [...]
|  |  |- __init__.py
|  |  |- [...]
|- setup.py

我想要的是:

/ #root
|- data/
|  |- resource1
|  |- [...]
|- src/
|  |- mypackage/
|  |  |- __init__.py
|  |  |- [...]
|- setup.py

如果它不是必需的话,我对拥有这么多子目录感到不舒服。我找不到原因,为什么我/ /将文件放在包目录中。使用如此多的嵌套子目录恕我直言也很麻烦。或者有任何理由可以证明这种限制吗?

4 个答案:

答案 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包之外 之一:

  1. 通过配置文件传入data的位置, 命令行参数或
  2. 将位置嵌入Python代码中。
  3. 如果您计划分发项目,这远远不太理想。如果确实想要这样做,您可以通过传入元组列表为每组文件指定目标,在目标系统上的任何位置安装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()