setuptools : 패키지 데이터 폴더 위치


98

나는 setuptools를 사용하여 파이썬 패키지를 배포합니다. 이제 추가 데이터 파일을 배포해야합니다.

setuptools 문서에서 수집 한 내용에서 패키지 디렉토리에 데이터 파일이 있어야합니다. 그러나 차라리 루트 디렉토리의 하위 디렉토리에 데이터 파일이 있습니다.

내가 피하고 싶은 것 :

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

대신 갖고 싶은 것 :

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

필수가 아니라면 너무 많은 하위 디렉터리가있는 것이 편하지 않습니다. 이유를 찾지 못했습니다. 패키지 디렉토리에 파일을 넣는 이유를 / have /합니다. 너무 많은 중첩 된 하위 디렉터리 IMHO로 작업하는 것도 번거 롭습니다. 아니면이 제한을 정당화 할만한 이유가 있습니까?


9
나는 자원 (문서, 이미지 등) 배포 'data_files'를 사용하는 방법에 대한 비슷한 질문을했다 : stackoverflow.com/questions/5192386/...을 ... 그리고 (이) 응답은 모두 대신 'package_data'를 사용했다. 이제 패키지 데이터를 사용하고 있지만, 내 패키지 안에 데이터와 문서를 넣어야한다는 것을 의미합니다. 즉, 소스 코드 사이에 섞여 있습니다. 나는 이것을 싫어한다. 내 소스를 검색 할 때 내가 찾고있는 클래스 정의뿐만 아니라 내 RST, HTML 및 중간 파일 내에서 수십 개의 언급을 찾을 수 있습니다. :-(
Jonathan Hartley

2
이 응답이 매우 늦었다는 것을 알고 있습니다. @JonathanHartley이지만 __init__.py파일이 비어 있더라도 파일 을 추가하여 모든 디렉토리를 "패키지"로 만들 수 있습니다 . 따라서 데이터 디렉토리를 빈 __init__.py파일로 분리 하여 패키지처럼 보이게 할 수 있습니다. 소스 트리 내에서 grep을 선택하지 못하도록해야하지만 Python 및 빌드 도구에서 여전히 패키지로 인식됩니다.
dhj

@dhj 흥미로운 아이디어, 감사합니다.
Jonathan Hartley

4
@dhj 그 접근 방식의 유일한 문제는 파이썬이 '데이터'라는 패키지를 설치했다고 생각한다는 것입니다. 설치 한 다른 패키지가 같은 방식으로 데이터를 패키징하려고하면 충돌하는 '데이터'패키지가 두 개 설치됩니다.
발가락

답변:


112

옵션 1 : 패키지 데이터로 설치

Python 패키지의 루트 내에 데이터 파일을 배치 할 때의 가장 큰 장점은 Windows, Mac, Linux, 일부 모바일 플랫폼 또는 Egg 내부와 같은 사용자 시스템에서 파일이 어디에 있는지 걱정하지 않아도된다는 것입니다. data설치 위치 나 방법에 관계없이 항상 Python 패키지 루트와 관련된 디렉토리를 찾을 수 있습니다 .

예를 들어 다음과 같은 프로젝트 레이아웃이있는 경우 :

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 코드에 위치를 포함합니다.

프로젝트를 배포 할 계획이라면 이것은 훨씬 덜 바람직합니다. 당신이 경우 정말 이 작업을 수행하려면, 당신은 당신을 설치할 수 있습니다 data당신은 튜플의리스트를 전달하여 각 파일 그룹에 대한 대상을 지정하여 대상 시스템에서 원하는 위치 :

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

업데이트 : Python 파일을 재귀 적으로 grep하는 셸 함수의 예 :

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

7
제가 상황을 이해하도록 도와 주셔서 대단히 감사합니다. 그래서 나는 당신과 다른 모든 사람들이 제안한 것처럼 package_data를 사용하여 실행하게되어 기쁩니다. 그러나 : 패키지 소스 디렉토리에 데이터와 문서를 넣는 것이 불편할 정도로 지저분하다는 것을 알게 된 것은 나뿐입니까? (예를 들어, 내 소스를 검색하면 문서에서 원하지 않는 히트가 수십 개 반환됩니다. 사용할 때마다 grep에 '--exclude-dir'매개 변수를 추가 할 수 있습니다. 프로젝트마다 다를 수 있지만 엉뚱 해 보입니다.) 그것은 뭔가 가능한 포함처럼 'SRC'하위 디렉터리 등 파괴 수입없이 내 패키지 디렉토리, 내부
조나단 하틀리

나는 보통 패키지 디렉토리 아래에 패키지에 필요한 데이터 파일 만 넣습니다. 문서를 data_files. 또한 grep이 Python이 아닌 파일을 무시하는 셸 별칭 (예 : grep_py.
samplebias 2011 년

안녕하세요 samplebias. 업데이트 해주셔서 감사합니다. 그래도 grep뿐만 아니라 텍스트 편집기 검색 파일에서 ctags, awk에 이르기 까지 모든 것이 있습니다. 나는 당신이 제안한대로 data_files에 문서를 넣도록 내 프로젝트를 재구성하려고 시도 할 것입니다. 돌아 가기 곧 ... :-)
조나단 하틀리

... 괜찮은 것 같습니다. 저를 올바른 길로 안내해 주셔서 감사합니다. +50 평판 포인트가 맛 있나요?
Jonathan Hartley 2011 년

감사! 잘 듣게되어 기쁩니다. 진전을 이루고 있습니다!
samplebias 2011 년

14

다음과 같은 구조를 유지할 수있는 좋은 타협점을 찾은 것 같습니다.

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

samplebias 답변에 설명 된 문제를 방지하려면 데이터를 package_data로 설치해야하지만 파일 구조를 유지하려면 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'를 지정하지 않아도되지만 좋은 타협이라고 생각합니다.


-4

기본적으로 setup ()에 * data_files * 인수로 무엇이든 줄 수 있다고 생각합니다 .


흠 ... distutils 문서에 있다는 것을 알 수 있지만 setuptools 문서에서는 볼 수 없습니다. 어쨌든 결국 어떻게 액세스 할 수 있을까요?
phant0m 2010

data_files는 여러 패키지간에 공유되는 데이터에만 사용해야한다고 생각합니다. 예를 들어 PyPI에서 pip 설치를 수행하면 data_files에 나열된 파일이 기본 Python 설치 디렉터리 바로 아래의 디렉터리에 설치됩니다. (즉, Python27 / Lib / site-packages / mypackage가 아니라 'Python27 / Lib'과 병행)
Jonathan Hartley
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.