430 Stimmen

Referenz requirements.txt für den install_requires kwarg in der Datei setuptools setup.py

Ich habe eine requirements.txt Datei, die ich mit Travis-CI verwende. Es scheint albern, die Anforderungen in beiden Dateien zu duplizieren requirements.txt y setup.py Ich hatte gehofft, ein Dateihandle an die Funktion install_requires kwarg in setuptools.setup .

Ist dies möglich? Wenn ja, wie sollte ich vorgehen?

Hier ist mein requirements.txt Datei:

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

26voto

sinoroc Punkte 13096

Erstens glaube ich, dass das Parsing requirements.txt um die Liste der Abhängigkeiten in den Paketmetadaten zu füllen, ist keine gute Idee. Die requirements.txt Datei und die Liste der "Installationsabhängigkeiten" sind zwei verschiedene Konzepte, sie sind nicht austauschbar . Es sollte umgekehrt sein, die Liste der Abhängigkeiten in den Paketmetadaten sollte als eine Art Quelle der Wahrheit betrachtet werden, und Dateien wie requirements.txt sollte von dort aus generiert werden. Zum Beispiel mit einem Werkzeug wie pip-compile . Siehe die Anmerkungen am Ende dieser Antwort.

Aber jeder hat andere Bedürfnisse, die zu unterschiedlichen Arbeitsabläufen führen. Damit ist also gesagt... Es gibt 3 Möglichkeiten, dies zu handhaben, je nachdem, wo Sie die Paket-Metadaten Ihres Projekts schreiben wollen: pyproject.toml , setup.cfg 或いは setup.py .


Ein Wort der Warnung!

Wenn Sie darauf bestehen, dass die Liste der Abhängigkeiten in den Paketmetadaten aus einer requirements.txt Datei, dann stellen Sie sicher, dass diese requirements.txt Datei ist in der "source distribution" enthalten ( sdist ), sonst schlägt die Installation aus offensichtlichen Gründen fehl.

Diese Techniken funktionieren nur bei einfachen requirements.txt Dateien. Siehe Analyse der Anforderungen auf der Dokumentationsseite für pkg_resources um Einzelheiten darüber zu erfahren, was gehandhabt wird. Kurz gesagt, jede Zeile sollte eine gültige PEP 508 Anforderung . Notationen, die wirklich spezifisch sind für pip werden nicht unterstützt und führen zu einem Fehler.


pyproject.toml

[project]
# ...
dynamic = ["dependencies"]

[tool.setuptools.dynamic]
# ...
dependencies = requirements.txt

setup.cfg

Seit setuptools Version 62.6 ist es möglich, etwas wie dieses in setup.cfg :

[options]
install_requires = file: requirements.txt

setup.py

Es ist möglich, eine relativ einfache requirements.txt Datei aus einer setuptools setup.py Skript ohne pip . Die setuptools Projekt enthält bereits die notwendigen Werkzeuge in seinem oberste Ebene Paket pkg_resources .

Das könnte mehr oder weniger so aussehen:

#!/usr/bin/env python

import pathlib

import pkg_resources
import setuptools

with pathlib.Path('requirements.txt').open() as requirements_txt:
    install_requires = [
        str(requirement)
        for requirement
        in pkg_resources.parse_requirements(requirements_txt)
    ]

setuptools.setup(
    install_requires=install_requires,
)

Anmerkungen :

24voto

Verwendung von parse_requirements ist problematisch, weil die Pip-API nicht öffentlich dokumentiert und unterstützt wird. In pip 1.6 wird diese Funktion tatsächlich verschoben, so dass bestehende Verwendungen dieser Funktion wahrscheinlich abbrechen werden.

Eine zuverlässigere Methode zur Beseitigung von Überschneidungen zwischen setup.py y requirements.txt ist es, Ihre Abhängigkeiten in setup.py und setzen dann -e . in Ihr requirements.txt Datei. Einige Informationen aus einer der pip Entwickler, die wissen, warum das der bessere Weg ist, finden Sie hier: https://caremad.io/blog/setup-vs-requirement/

19voto

fabianvf Punkte 835

Die meisten anderen Antworten oben funktionieren nicht mit der aktuellen Version der API von pip. Hier ist der korrekte* Weg, es mit der aktuellen Version von pip zu tun (6.0.8 zum Zeitpunkt des Schreibens, funktioniert auch in 7.1.2. Sie können Ihre Version mit pip -V überprüfen).

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
    ....
)

* Korrekt, denn so kann parse_requirements mit dem aktuellen pip verwendet werden. Wahrscheinlich ist es trotzdem nicht der beste Weg, da pip, wie die Poster oben sagten, nicht wirklich eine API unterhält.

13voto

vdboor Punkte 20756

Installieren Sie das aktuelle Paket in Travis. Dies vermeidet die Verwendung eines requirements.txt Datei. Zum Beispiel:

language: python
python:
  - "2.7"
  - "2.6"
install:
  - pip install -q -e .
script:
  - python runtests.py

6voto

Diego Navarro Punkte 8566

from pip.req import parse_requirements hat bei mir nicht funktioniert, und ich glaube, das liegt an den leeren Zeilen in meiner requirements.txt, aber diese Funktion funktioniert

def parse_requirements(requirements):
    with open(requirements) as f:
        return [l.strip('\n') for l in f if l.strip('\n') and not l.startswith('#')]

reqs = parse_requirements(<requirements_path>)

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X