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.
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
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 vorhandenePipfile.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:
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.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.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 ausPipfile.lock
ist für mich bequemer:jq -r '.default | to_entries[] | .key + .value.version' \ Pipfile.lock > requirements.txt
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.
jq
mit brew install jq
requirements.txt
aus Pipfile.lock
zu generierenEs 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
Hilfreichster Kommentar
Du kannst rennen