[python] setuptools setup.py 파일의 install_requires kwarg에 대한 참조 requirements.txt

requirements.txtTravis-CI와 함께 사용 중인 파일이 있습니다. 모두의 요구 사항을 복제하는 어리석은 것 requirements.txtsetup.py난에 파일 핸들을 전달하기 위해 기대했다, 그래서 install_requires에서 kwarg setuptools.setup.

이게 가능해? 그렇다면 어떻게해야합니까?

requirements.txt파일 은 다음과 같습니다 .

guessit>=0.5.2
tvdb_api>=1.8.2
hachoir-metadata>=1.3.3
hachoir-core>=1.3.3
hachoir-parser>=1.3.4



답변

당신은 그것을 주위를 뒤집어 목록에서 종속성을 수 setup.py및 단일 문자가 – 점을 .에 – requirements.txt대신.


또는 권장 requirements.txt하지 않더라도 (다음으로 테스트 한 pip 9.0.1) 해킹을 사용 하여 파일 (URL로 외부 요구 사항을 참조하지 않는 경우) 을 파싱 할 수 있습니다 .

install_reqs = parse_requirements('requirements.txt', session='hack')

그러나 환경 마커 는 필터링하지 않습니다 .


이전 버전의 pip, 특히 6.0보다 오래된 버전에서는 이를 달성하는 데 사용할 수있는 공개 API가 있습니다. 요구 사항 파일은 주석 ( #)을 포함 할 수 있으며 다른 파일 ( --requirement또는 -r)을 포함 할 수 있습니다 . 따라서 정말로 파싱 requirements.txt하려면 pip 파서를 사용할 수 있습니다.

from pip.req import parse_requirements

# parse_requirements() returns generator of pip.req.InstallRequirement objects
install_reqs = parse_requirements(<requirements_path>)

# reqs is a list of requirement
# e.g. ['django==1.5.1', 'mezzanine==1.4.6']
reqs = [str(ir.req) for ir in install_reqs]

setup(
    ...
    install_requires=reqs
)


답변

그것의 얼굴에, 그 보이지 않는 requirements.txtsetup.py바보 중복, 그러나 그것은 형태가 유사한 반면, 의도 한 기능이 매우 다르다는 것을 이해하는 것이 중요합니다.

종속성을 지정할 때 패키지 작성자의 목표는 “이 패키지를 설치할 때마다이 패키지가 작동하기 위해 필요한 다른 패키지입니다”라고 말하는 것입니다.

반대로 배포 작성자 (다른 시간에 같은 사람 일 수 있음)는 “우리가 함께 모아서 테스트하여 설치해야하는 패키지 목록이 있습니다”라는 점에서 다른 역할을합니다.

패키지 작성자는 다양한 시나리오에 대해 작성합니다. 그들이 알지 못하는 방식으로 작업을 수행하고 패키지와 함께 어떤 패키지가 설치 될지 알 수 없기 때문입니다. 좋은 이웃이되고 다른 패키지와의 종속성 버전 충돌을 피하려면 가능한 한 다양한 종속성 버전을 지정해야합니다. 이것이하는 일 install_requires입니다 setup.py.

배포 작성자는 매우 다른 매우 구체적인 목표, 즉 특정 컴퓨터에 설치된 설치된 응용 프로그램 또는 서비스의 단일 인스턴스를 작성합니다. 배포를 정확하게 제어하고 올바른 패키지를 테스트하고 배포하려면 배포 작성자가 종속성 및 종속성의 종속성을 포함하여 설치할 모든 패키지의 정확한 버전과 소스 위치를 지정해야합니다. 이 사양을 사용하면 배포를 여러 컴퓨터에 반복적으로 적용하거나 테스트 컴퓨터에서 테스트 할 수 있으며 배포 작성자는 매번 동일한 패키지가 배포 될 것을 확신 할 수 있습니다. 이것이 무엇을 하는가 requirements.txt입니다.

패키지와 버전의 큰 목록처럼 보이지만이 두 가지 작업은 매우 다릅니다. 그리고 이것을 섞어서 틀리게 만드는 것은 확실히 쉽습니다! 그러나 이것을 생각하는 올바른 방법 requirements.txt은 모든 다양한 setup.py패키지 파일 의 요구 사항에 의해 제기 된 “질문”에 대한 “답변” 입니다. 직접 작성하는 대신, pip에게 setup.py원하는 패키지 세트의 모든 파일 을보고, 모든 요구 사항에 맞는 패키지 세트를 찾은 다음, 설치 후 “고정”으로 생성하여 생성됩니다. “해당 패키지 목록을 텍스트 파일로 저장합니다 (여기서 pip freeze이름이 나오는 곳).

따라서 테이크 아웃 :

  • setup.py여전히 실행 가능한 가장 느슨한 종속성 버전을 선언해야합니다. 그 작업은 특정 패키지가 작동 할 수있는 것을 말하는 것입니다.
  • requirements.txt전체 설치 작업을 정의하는 배포 매니페스트이며 어떤 패키지에 묶여 있다고 생각해서는 안됩니다. 배포 작업을 수행하는 데 필요한 모든 패키지의 전체 목록을 선언해야합니다.
  • 이 두 가지 내용은 기존과 다른 내용과 이유를 가지고 있기 때문에 서로를 단순히 복사하는 것은 불가능합니다.

참고 문헌 :


답변

파일 핸들을 사용할 수 없습니다. install_requires인수는 수 만 문자열이나 문자열 목록 수 .

물론 설정 스크립트에서 파일을 읽고 문자열 목록으로 전달할 수 install_requires있습니다.

import os
from setuptools import setup

with open('requirements.txt') as f:
    required = f.read().splitlines()

setup(...
install_requires=required,
...)


답변

요구 사항 파일은 확장 된 pip 형식을 사용합니다. setup.py예를 들어 일부 종속 항목의 정확한 URL을 지정하거나 pip freeze전체 패키지 세트를 알려진 작업으로 고정하는 출력을 지정하는 등보다 강력한 제한 조건 으로 보완해야하는 경우에만 유용 합니다. 버전. 추가 제약이 필요하지 않은 경우을 사용하십시오 setup.py. requirements.txt어쨌든 실제로 배송해야 한다고 생각되면 한 줄로 만들 수 있습니다.

.

유효하며 setup.py동일한 디렉토리에있는 내용을 정확하게 참조하십시오 .


답변

이 질문에 대한 정확한 대답은 아니지만 이 문제를 잘 이해 하려면 Donald Stufft의 블로그 게시물 ( https://caremad.io/2013/07/setup-vs-requirement/) 을 추천합니다. 나는 그것을 큰 성공을 위해 사용하고 있습니다.

즉, requirements.txt아닌 setup.py다른,하지만 배포 보완. 에 패키지 종속성의 적절한 추상화를 유지하십시오 setup.py. requirements.txt개발, 테스트 또는 프로덕션을 위해 특정 버전의 패키지 종속성을 가져 오도록 설정하십시오 .

예를 들어 아래의 저장소에 패키지가 포함 된 경우 deps/:

# fetch specific dependencies
--no-index
--find-links deps/

# install package
# NOTE: -e . for editable mode
.

pip는 패키지를 실행 setup.py하고에 선언 된 특정 버전의 종속성을 설치합니다 install_requires. 이중성이 없으며 두 아티팩트의 목적이 유지됩니다.


답변

parse_requirementspip API가 공개적으로 문서화되고 지원되지 않기 때문에 사용 에 문제가 있습니다. pip 1.6에서는 해당 기능이 실제로 이동하므로 기존 기능을 사용하기가 어려울 수 있습니다.

더 신뢰할 수있는 방법 사이의 중복을 제거하기 setup.pyrequirements.txt특정에 당신의 종속성을에 setup.py다음 넣어 -e .당신에 requirements.txt파일. pip왜 더 좋은 방법인지 에 대한 개발자 중 한 사람의 정보는 https://caremad.io/blog/setup-vs-requirement/에서 확인할 수 있습니다.


답변

위의 다른 답변 대부분은 현재 버전의 pip API에서 작동하지 않습니다. 현재 버전의 pip (작성 당시 6.0.8, 7.1.2에서 작동했습니다. pip -V로 버전을 확인할 수 있습니다)로 올바른 방법을 사용하십시오.

from pip.req import parse_requirements
from pip.download import PipSession

install_reqs = parse_requirements(<requirements_path>, session=PipSession())

reqs = [str(ir.req) for ir in install_reqs]

setup(
    ...
    install_requires=reqs
    ....
)

* 현재 pip와 함께 parse_requirements를 사용하는 방법이라는 점에서 정확합니다. 위의 포스터가 말했듯이 pip는 실제로 API를 유지 관리하지 않기 때문에 여전히 최선의 방법은 아닙니다.