Pipenv: Erzeugt requirements.txt aus Pipfile.lock

Erstellt am 31. Jan. 2019  ·  25Kommentare  ·  Quelle: pypa/pipenv

Wie erstelle ich eine requirements.txt -Datei aus vorhandenen Pipfile.lock ohne Sperren?
Wenn ich pipenv lock -r ausführe, ignoriert es vorhandene Pipfile.lock und führt den Sperrvorgang erneut durch.

Dafür gibt es einen Workaround:

$ pipenv sync
$ pipenv run pip freeze

In meiner speziellen Situation baue ich ein Docker-Image und verwende requirements.txt in Dockerfile . Ich möchte vermeiden, eine virtuelle Umgebung auf dem Hostcomputer zu erstellen, nur um requirements.txt erstellen zu können.

Hilfreichster Kommentar

Du kannst rennen

pipenv run pip freeze > requirements.txt

Alle 25 Kommentare

Pipenv bietet dafür keine Möglichkeit, Sie können nach anderen pipfile-Dienstprogrammbibliotheken wie pipfile-requirements suchen

Du kannst rennen

pipenv run pip freeze > requirements.txt

Du kannst rennen

pipenv run pip freeze > requirements.txt

Das habe ich im ersten Post als Workaround erwähnt.

Aber es funktioniert nur, wenn Sie Ihre pipenv-Umgebung synchronisiert haben (alle Pakete sind installiert).
Das Extrahieren von Abhängigkeiten direkt aus Pipfile.lock ist für mich bequemer:

jq -r '.default
        | to_entries[]
        | .key + .value.version' \
    Pipfile.lock > requirements.txt

Blogeintrag
jq-Tool

LOL, ich habe diese Bibliothek bereits erwähnt.

Ich persönlich mag es nicht, dafür eine eigene Bibliothek zu haben. Außerdem besteht eine höhere Wahrscheinlichkeit, dass ein Teammitglied bereits jq oder ein anderes Allzwecktool installiert hat.

du kannst sogar rennen

 pipenv lock --requirements > requirements.txt

Es wird nicht so funktionieren, wie Sie es erwarten, denn wie ich geschrieben habe:

Wenn ich pipenv lock -r ausführe, ignoriert es vorhandene Pipfile.lock und führt den Sperrvorgang erneut durch.

Mit anderen Worten, es führt ein Update durch, das möglicherweise eine Distribution zerstören kann. Stellen Sie sich vor, Sie generieren requirements.txt , um es in Dockerfile zu verwenden, um ein Docker-Image zu erstellen. Lokal funktioniert Ihre Anwendung, aber wenn Sie requirements.txt mit pipenv lock generieren, werden die Anforderungen möglicherweise auf inkompatible oder nur fehlerhafte Versionen aktualisiert (hoffentlich ist dies jedoch ein seltener Fall). Und Sie werden dies nicht wissen, bevor Sie das Bild ausführen. Daher müssen Sie die App erneut testen, nachdem Sie pipenv lock ausgeführt haben.

Wenn Sie jq nicht verwenden möchten, verwenden Sie besser den Ansatz, den ich im ersten Beitrag mit pipenv sync vorgeschlagen habe (der keine Aktualisierung durchführt).

@Zebradil Ihr jq Einzeiler-Ansatz ist viel einfacher als das eigene pipfile-requirements -Paket von @frostming (über 100 Zeilen Python-Code), da ich bereits jq installiert habe, keine anderen Abhängigkeiten erforderlich, das ist großartig.

Nach ein paar Git-Commits bemerkte ich jedoch den Unterschied zwischen dem, was pipenv lock --requirements ausgibt, und dem, was jq durch die Datei Pipfile.lock #$ liest und ausgibt:

  • Die Ausgabe jq hat nicht -i https://pypi.org/simple als allererste Zeile, im Gegensatz zu dem, was pipenv lock --r immer als allererste Zeile einfügt.
  • Die Ausgabe jq enthält keine Annotation für Pakete. Beispiel: Die Ausgabe pipenv lock --r hat diese Zeile appnope==0.1.0 ; sys_platform == 'darwin' , aber in der Ausgabe jq ist sie appnope==0.1.0 . Ein weiteres Beispiel ist pipenv lock -r generiert pexpect==4.7.0 ; sys_platform != 'win32' während jq pexpect==4.7.0 $ generiert, nicht sicher, ob dies wichtig ist oder nicht.
  • Die Reihenfolge der Anforderungsdateipakete unterscheidet sich zwischen den beiden Ausgaben. jq , das vermutlich die Paketreihenfolge in der Pipfile.lock -Datei übernimmt, die immer nach aufsteigender Reihenfolge in Alphabet und Zeichenlänge sortiert, zum Beispiel steht flask vor flask-sqlalchemy oder beliebige flask-XXXXX Pakete, während pipenv lock --r flask hinter flask-sqlalchemy $ ausgibt, was sich von der Reihenfolge in Pipfile.lock unterscheidet. Dies ist ein großes Ärgernis, da es keinen minimalen Git-Diff generiert. Ich würde dies für einen Fehler in pipenv halten.

Hi @ye , schöner Vergleich der Methoden. Es kann Menschen helfen, die richtige Lösung für ihre spezielle Situation zu wählen und Vorbehalte zu vermeiden.

Ja, wie Sie sagten, hat der vorgeschlagene Ansatz mit jq eine eingeschränkte Funktionalität. Es ist möglich, es zu erweitern, um Anmerkungen und Paketindex-URLs hinzuzufügen, aber ich habe derzeit keine Notwendigkeit dafür.

Um Unterschiede in der generierten „requirements.txt“ zu vermeiden, sollte man erwägen, jedes Mal denselben Ansatz zu verwenden. In ähnlicher Weise kann die Verwendung unterschiedlicher Codeformatierungstools zu inkonsistenten Ergebnissen führen. Also ich sehe hier kein Problem.

Du kannst rennen

pipenv run pip freeze > requirements.txt

Das habe ich im ersten Post als Workaround erwähnt.

Aber es funktioniert nur, wenn Sie Ihre pipenv-Umgebung synchronisiert haben (alle Pakete sind installiert).
Das Extrahieren von Abhängigkeiten direkt aus Pipfile.lock ist für mich bequemer:

jq -r '.default
        | to_entries[]
        | .key + .value.version' \
    Pipfile.lock > requirements.txt

Blogeintrag
jq-Tool

Hallo,

Danke für deine Lösung. Ich bin auf dasselbe Problem gestoßen, aber ich brauche auch die Definition von Quellen, die von pipenv lock -r erstellt wurden, dh: -i, --extra-index-url. Das liegt daran, dass ich mit privaten Quellen arbeite.

@Zebradil Ich glaube, das hast du erwähnt.

Also habe ich ein weiteres minimales Skript ohne Abhängigkeiten in Python erstellt, das diese Funktionalität enthält. Es erweitert auch env vars, falls Sie Ihre Quellen auf diese Weise in Ihrem Pipfile definiert haben.

Wenn jemand einen Blick darauf werfen möchte, lasse ich es hier: https://gist.github.com/rcastill/dab85c234dd10fa7af56755116c75aee

Falls es jemand anderem hilft, hier ist, wie man die Hashes in die Ergebnisse einbezieht:

 jq --raw-output '.default | to_entries[] | .key + .value.version + (.value.hashes | map(" --hash=\(.)") | join(""))' Pipfile.lock

Dadurch entstehen Einträge wie

paramiko==2.6.0 --hash=sha256:99f0179bdc176281d21961a003ffdb2ec369daac1a1007241f53374e376576cf --hash=sha256:f4b2edfa0d226b70bd4ca31ea7e389325990283d301274514f274a

Dadurch erzwingt pip die Hashes.

Wenn Sie nur die Anforderungen aufnehmen möchten, die in der ursprünglichen Anforderungsdatei enthalten waren (vorausgesetzt, sie wurden bereits mit == auf eine bestimmte Version festgelegt):

 jq --raw-output '.default | to_entries[] | .key + .value.version + (.value.hashes | map(" --hash=\(.)") | join(""))' Pipfile.lock | grep --file=<(grep --only-matching --perl-regexp '^.*(?===)' requirements.txt | tr '[:upper:]' '[:lower:]') > new.txt && mv new.txt requirements.txt

tr ist erforderlich, da die Dateien requirements.txt Paketnamen mit gemischter Groß-/Kleinschreibung enthalten können, pipenv install -r requirements.txt sie jedoch in Pipfile klein schreibt.

Hier ist ein kleines Python-Skript, falls Sie die Pipfile (nicht die Lock-Datei) in eine requirements.txt-Datei umwandeln möchten.

import configparser


def main():
    parser = configparser.ConfigParser()
    parser.read("Pipfile")

    packages = "packages"
    with open("requirements.txt", "w") as f:
        for key in parser[packages]:
            value = parser[packages][key]
            f.write(key + value.replace("\"", "") + "\n")


if __name__ == "__main__":
    main()

@frostming Hallo, ich fand https://github.com/frostming/pipfile-requirements nützlich, aber warum wurde es nicht in pipenv integriert?

@linusguan Das Tool existiert für diejenigen, die die große pipenv-Bibliothek nicht installieren möchten. Wenn Sie pipenv installiert haben, können Sie pipenv lock -r verwenden

@frostming Ich finde es sehr nützlich für die Verwendung mit anderen Tools, die pipfile.lock nicht unterstützen.
Das Problem mit pipenv lock -r ist, dass pipfile.lock aktualisiert wird, sodass ich es nicht verwenden kann, um zusammen mit anderen Tools einen deterministischen Build zu erstellen. Etwas wie pipenv lock -r --ignore-pipfile wäre ideal.

Hier ist noch ein weiteres Python-Skript zum Generieren von requirements.txt aus der Pipfile.lock-Datei mit Hashes:

import os
import json

__dir__ = os.path.dirname(os.path.realpath(__file__))


def read_json_file(path):
    with open(path) as f:
        return json.load(f)


def main():
    root = read_json_file(os.path.join(__dir__, 'Pipfile.lock'))

    for name, pkg in root["default"].items():
        version = pkg["version"]
        sep = lambda i: "" if i == len(pkg["hashes"]) - 1 else " \\"
        hashes = [f'--hash={t}{sep(i)}' for i, t in enumerate(pkg["hashes"])]
        tail = '' if len(hashes) == 0 else f' {hashes[0]}'
        print(f'{name} {version}{tail}')
        for h in hashes[1:]:
            print(f'    {h}')


if __name__ == "__main__":
    main()

@Zebradil Danke! Deine Lösung hat bei mir wirklich funktioniert.

  • Zuerst installiere ich das Tool jq mit brew install jq
  • Verwenden Sie dann Ihr Skript, um requirements.txt aus Pipfile.lock zu generieren

Es sieht so aus, als könnte dies mit dem Flag --keep-outdated gelöst werden, oder irre ich mich?

pipenv lock --keep-outdated -d -r > requirements.txt

PS, das ist eine ärgerlich ausführliche Flagge, um dies zu lösen

Leider scheint @jacobisaliveandwell das Flag --keep-outdated zu aktualisieren, um Unterabhängigkeiten zu aktualisieren: https://github.com/pypa/pipenv/issues/3975

@paytonrules Das ist ein Fehler, aber der Geist der Flagge ist immer noch die Antwort auf dieses Problem.

PS Dafür braucht man keinen Daumen nach unten :-(

Ich möchte nur erwähnen, dass es Unterschiede zu den angegebenen Problemumgehungen gibt:
pipenv run pip freeze gibt Paketnamen zurück, bei denen die Groß-/Kleinschreibung beachtet wird (zB PyYAML )
pipenv lock --requirements gibt alle Paketnamen in Kleinbuchstaben zurück (z. B. pyyaml )

@ Darkless012 Sie sollten ein anderes Ticket öffnen, das dies beschreibt, und auf dieses Problem als verwandt verweisen.

Reine Bash, nur Pakete, sonst nichts, falls jemand jq nicht installieren kann oder will, nur für den Fall, dass es jemandem hilft,

cat Pipfile.lock \
  | grep -B1 '"hashes"\|"version": ' \
  | grep -v '"markers": \|"hashes": ' \
  | grep ": {\|version" \
  | sed -e 's/: {$//g' \
  | tr '\n' ',' | tr -s ' ' ' ' \
  | sed -e 's/, "version": "//g;s/", "/ /g;s/"//g;s/,//g' \
  | tr ' ' '\n' \
| grep -v "^$" > requirements.txt

Gibt es irgendetwas, das auch die Hashes aus dem Pipfile in die requirements.txt kopiert (zB bei so etwas wie einer Plattform-str), damit pip install --require-hashes funktioniert?

$ pip install --help
# ...
  --require-hashes            Require a hash to check each requirement against, for repeatable installs. This option is implied when any package in a
                              requirements file has a --hash option.

Sie können micropipenv verwenden, das Pipenv.lock-Dateien (auch Poetry.lock) in requirements.txt (raw requirements.txt oder Pip-Tools-kompatibel) konvertieren kann. Siehe https://github.com/thoth-station/micropipenv/#micropipenv -requirements--micropipenv-req

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen