setuptools:包数据文件夹位置

pha*_*t0m 81 python setuptools

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

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

我想避免的:

/ #root
|- src/
|  |- mypackage/
|  |  |- data/
|  |  |  |- resource1
|  |  |  |- [...]
|  |  |- __init__.py
|  |  |- [...]
|- setup.py
Run Code Online (Sandbox Code Playgroud)

我想要的是:

/ #root
|- data/
|  |- resource1
|  |- [...]
|- src/
|  |- mypackage/
|  |  |- __init__.py
|  |  |- [...]
|- setup.py
Run Code Online (Sandbox Code Playgroud)

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

sam*_*ias 100

选项1:作为包数据安装

将数据文件放在Python包的根目录中的主要优点是,它可以让您避免担心文件在用户系统上的位置,可能是Windows,Mac,Linux,某些移动平台或Egg内部.data无论在何处或如何安装,您始终可以找到相对于Python包根目录的目录.

例如,如果我有这样的项目布局:

project/
    foo/
        __init__.py
        data/
            resource1/
                foo.txt
Run Code Online (Sandbox Code Playgroud)

您可以添加一个函数来__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')
Run Code Online (Sandbox Code Playgroud)

输出:

/Users/pat/project/foo/data/resource1/foo.txt
Run Code Online (Sandbox Code Playgroud)

将项目作为Egg安装后,路径data将发生变化,但代码不需要更改:

/Users/pat/virtenv/foo/lib/python2.6/site-packages/foo-0.0.0-py2.6.egg/foo/data/resource1/foo.txt
Run Code Online (Sandbox Code Playgroud)

选项2:安装到固定位置

另一种方法是将数据放在Python包之外,然后:

  1. data通过配置文件,命令行参数或传递的位置
  2. 将位置嵌入到Python代码中.

如果您计划分发您的项目,这是不太理想的.如果您真的想这样做,您可以data通过传入元组列表为每组文件指定目标,在目标系统上安装您喜欢的任何位置:

from setuptools import setup
setup(
    ...
    data_files=[
        ('/var/data1', ['data/foo.txt']),
        ('/var/data2', ['data/bar.txt'])
        ]
    )
Run Code Online (Sandbox Code Playgroud)

更新:递归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']}
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢您帮助我了解情况.所以我很乐意和你(以及其他所有人)建议一样使用package_data.但是:只有我发现将他们的数据和文档放在他们的包源目录中是不方便的杂乱吗?(例如,从我的文档中点击我的源代码会返回数十个不需要的命中.我可以在每次使用它时将grep添加'--exclude-dir'参数,这在一个项目与下一个项目之间会有所不同,但这看起来很蹩脚)是有可能在我的包dir中包含一个'src'子目录,而不会破坏导入等 (5认同)

pol*_*zul 12

我想我找到了一个很好的折衷方案,可以让你保留以下结构:

/ #root
|- data/
|  |- resource1
|  |- [...]
|- src/
|  |- mypackage/
|  |  |- __init__.py
|  |  |- [...]
|- setup.py
Run Code Online (Sandbox Code Playgroud)

您应该将数据安装为package_data,以避免samplebias中描述的问题,但是为了保留您应该添加到setup.py的文件结构:

try:
    os.symlink('../../data', 'src/mypackage/data')
    setup(
        ...
        package_data = {'mypackage': ['data/*']}
        ...
    )
finally:
    os.unlink('src/mypackage/data')
Run Code Online (Sandbox Code Playgroud)

这样我们就可以"及时"创建适当的结构,并保持我们的源树的组织.

要在代码中访问此类数据文件,您只需"使用:

data = resource_filename(Requirement.parse("main_package"), 'mypackage/data')

我仍然不喜欢在代码中指定'mypackage',因为数据可能与此模块无关,但我认为这是一个很好的折衷方案.