2010-12-23 40 views
59

我使用setuptools来分发我的python包。现在我需要分发更多的数据文件。setuptools:包数据文件夹位置

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

我想什么来避免:

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

我想有代替:

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

我只是觉得不舒服有这么多的子目录,如果它不是必需的。我无法找到一个理由,为什么我/有/将文件放在软件包目录中。使用这么多嵌套的子目录恕我直言,也很麻烦。或者是否有任何理由支持这一限制?

+6

我问了一个类似的问题,关于使用'data_files'来分发资源(文档,图像等):http://stackoverflow.com/questions/5192386/installing-my-sdist-from-pypi-puts-the-文件在意想不到的地方 ...和(两个)响应都表示使用'package_data'来代替。现在我使用包数据,但这意味着我必须将我的数据和文档放入我的包中,即混入我的源代码中。我不喜欢这个。在对我的源代码进行清理时,我发现不仅仅是我正在搜索的类定义,还有几十个他们在我的RST,HTML和中间文件中提到的内容。 :-( – 2011-03-25 09:33:40

+2

我知道这个答案很晚,@JonathanHartley,但是你可以通过添加一个`__init __。py`文件来使任何目录成为一个“包”,即使这个文件是空白的。所以你可以保持一个数据目录的分离用一个空的`__init __。py`文件来使它看起来像一个包,它应该保持你的源代码树中的grep不会被选中,但它仍然会被python及其构建工具识别为一个包。 – dhj 2014-09-04 03:32:50

+0

@dhj An有趣的想法,谢谢 – 2014-09-05 21:01:14

回答

83

选项1:安装的包数据

将数据文件的Python包 根内的主要优点是,它可以让你避免担心其中的文件将居住在用户的 系统,这可能是Windows,Mac,Linux,一些移动平台,或者一个蛋的内部。无论在何处安装,您都可以通过 找到相对于您的Python软件包根目录的目录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 

该项目安装后作为一个例子克路径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代码中。

如果您计划分发您的项目,这是远远不可取的。

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

更新:如果你真的要做到这一点,你可以随时随地通过传递一个元组列表确定各组文件的目的地喜欢在目标系统上安装data:一个shell函数的例子递归grep的Python文件:

atlas% function grep_py { find . -name '*.py' -exec grep -Hn $* {} \; } 
atlas% grep_py ": \[" 
./setup.py:9: package_data={'foo': ['data/resource1/foo.txt']} 
-3

我认为你基本上可以给任何东西作为参数* data_files *到setup()

1

我用setuptools的创建本地OS包,比如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/之下。

2

我想我找到了一个很好的妥协,这将让你十个分量的结构如下:

/ #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')

我还是不喜欢在代码中指定“mypackage的”,因为数据可能什么都没有做必要的这个模块,但我想它是一个很好的妥协。