Comment générer un fichier requirements.txt
à partir de Pipfile.lock
existant sans verrouiller ?
Lorsque j'exécute pipenv lock -r
, il ignore les Pipfile.lock
existants et relance le processus de verrouillage.
Il existe une solution de contournement pour cela :
$ pipenv sync
$ pipenv run pip freeze
Dans ma situation particulière, je construis une image docker et j'utilise requirements.txt
dans Dockerfile
. J'aimerais éviter de créer un environnement virtuel sur la machine hôte juste pour pouvoir créer requirements.txt
.
Pipenv ne fournit pas un moyen pour cela, vous pouvez rechercher d'autres bibliothèques d'utilitaires pipfile telles que pipfile-requirements
tu peux courir
pipenv run pip freeze > requirements.txt
tu peux courir
pipenv run pip freeze > requirements.txt
C'est ce que j'ai mentionné comme solution de contournement dans le premier post.
Mais cela ne fonctionne que si votre environnement pipenv est synchronisé (tous les packages sont installés).
Extraire les dépendances directement de Pipfile.lock
est plus pratique pour moi :
jq -r '.default
| to_entries[]
| .key + .value.version' \
Pipfile.lock > requirements.txt
LOL, j'ai déjà mentionné cette bibliothèque.
Personnellement, je n'aime pas avoir une bibliothèque dédiée à cela. De plus, il y a plus de chances qu'un membre de l'équipe ait déjà installé jq
ou un autre outil à usage général.
tu peux même courir
pipenv lock --requirements > requirements.txt
Cela ne fonctionnera pas comme prévu, car, comme je l'ai écrit:
Lorsque j'exécute
pipenv lock -r
, il ignorePipfile.lock
existant et relance le processus de verrouillage.
En d'autres termes, il effectue une mise à jour, ce qui peut potentiellement détruire une distribution. Imaginez, vous générez requirements.txt
pour l'utiliser dans Dockerfile pour créer une image docker. Localement, votre application fonctionne, mais lorsque vous générez requirements.txt
en utilisant pipenv lock
, les exigences peuvent être mises à jour vers des versions incompatibles ou simplement cassées (espérons que c'est un cas rare, cependant). Et vous ne le saurez pas avant d'exécuter l'image. Vous devrez donc tester à nouveau l'application après avoir exécuté pipenv lock
.
Si vous ne voulez pas utiliser jq
, alors mieux vaut utiliser l'approche que j'ai proposée dans le premier message avec pipenv sync
(qui ne fait pas de mise à jour).
@Zebradil votre approche oneliner jq
est beaucoup plus simple que le propre paquet pipfile-requirements
de @frostming (plus de 100 lignes de code python) puisque j'ai déjà installé jq
, pas d'autres dépendances obligatoire, ce qui est super.
Cependant, après quelques commits git, j'ai remarqué la différence entre ce que pipenv lock --requirements
produit et ce que jq
glane dans le fichier Pipfile.lock
et imprime :
jq
n'a pas -i https://pypi.org/simple
comme toute première ligne, contrairement à ce que pipenv lock --r
insère toujours comme toute première ligne.jq
n'inclut pas l'annotation pour les packages. Par exemple : la sortie pipenv lock --r
a cette ligne appnope==0.1.0 ; sys_platform == 'darwin'
, mais dans la sortie jq
, c'est appnope==0.1.0
. Un autre exemple est pipenv lock -r
génère pexpect==4.7.0 ; sys_platform != 'win32'
alors que jq
génère pexpect==4.7.0
, je ne sais pas si cela compte ou non.jq
qui prend vraisemblablement l'ordre du paquet dans le fichier Pipfile.lock
, qui trie toujours par ordre croissant dans les alphabets et la longueur des caractères, par exemple, flask
est devant flask-sqlalchemy
ou n'importe quel package flask-XXXXX
, alors que pipenv lock --r
produit flask
derrière flask-sqlalchemy
, ce qui est différent de l'ordre dans Pipfile.lock
. C'est un inconvénient majeur car cela ne génère pas de git diff minimum. Je considérerais qu'il s'agit d'un bogue dans pipenv
.Salut @ye , belle comparaison des méthodes. Cela pourrait aider les gens à choisir la solution appropriée à leur situation particulière et à éviter les mises en garde.
Oui, comme vous l'avez dit, l'approche proposée avec jq
a des fonctionnalités limitées. Il est possible de l'étendre pour ajouter des annotations et une URL d'index de package, mais je n'en ai pas besoin pour le moment.
Pour éviter d'avoir des différences dans requirements.txt généré, il faut envisager d'utiliser la même approche à chaque fois. De la même manière, l'utilisation d'outils de formatage de code différents peut conduire à des résultats incohérents. Donc, je ne vois pas de problème ici.
tu peux courir
pipenv run pip freeze > requirements.txt
C'est ce que j'ai mentionné comme solution de contournement dans le premier post.
Mais cela ne fonctionne que si votre environnement pipenv est synchronisé (tous les packages sont installés).
Extraire les dépendances directement dePipfile.lock
est plus pratique pour moi :jq -r '.default | to_entries[] | .key + .value.version' \ Pipfile.lock > requirements.txt
Salut,
Merci pour votre solution. J'ai rencontré le même problème mais j'ai aussi besoin de la définition des sources créées par pipenv lock -r
, c'est-à-dire : -i, --extra-index-url. C'est parce que je travaille avec des sources privées.
@Zebradil Je pense que vous l'avez mentionné.
J'ai donc créé un autre script minimal sans dépendances en python qui inclut cette fonctionnalité. Il développe également env vars au cas où vos sources seraient définies de cette façon dans votre Pipfile.
Si quelqu'un veut jeter un coup d'œil, je le laisserai ici : https://gist.github.com/rcastill/dab85c234dd10fa7af56755116c75aee
Au cas où cela aiderait quelqu'un d'autre, voici comment inclure les hachages dans les résultats :
jq --raw-output '.default | to_entries[] | .key + .value.version + (.value.hashes | map(" --hash=\(.)") | join(""))' Pipfile.lock
Cela crée des entrées comme
paramiko==2.6.0 --hash=sha256:99f0179bdc176281d21961a003ffdb2ec369daac1a1007241f53374e376576cf --hash=sha256:f4b2edfa0d226b70bd4ca31ea7e389325990283da23755
Ce qui fait pip
applique les hachages.
Si vous souhaitez inclure uniquement les exigences qui se trouvaient dans le fichier d'exigences d'origine (à condition qu'elles aient déjà été verrouillées sur une version spécifique avec ==
) :
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
est nécessaire car les fichiers requirements.txt peuvent contenir des noms de packages à casse mixte, mais pipenv install -r requirements.txt
les met en minuscules dans Pipfile.
Voici un petit script python au cas où vous voudriez transformer le Pipfile
(pas le fichier de verrouillage) en un fichier requirements.txt.
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 Bonjour, j'ai trouvé https://github.com/frostming/pipfile-requirements utile mais pourquoi n'a-t-il pas été intégré à pipenv ?
@linusguan L'outil existe pour ceux qui ne veulent pas installer la grosse bibliothèque pipenv, quand vous avez installé pipenv, vous pouvez utiliser pipenv lock -r
@frostming Je le trouve très utile pour une utilisation avec d'autres outils qui ne prennent pas en charge pipfile.lock.
Le problème avec pipenv lock -r
est qu'il met à jour pipfile.lock donc je ne peux pas l'utiliser pour produire une construction déterministe avec d'autres outils. Quelque chose comme pipenv lock -r --ignore-pipfile
serait idéal.
Voici encore un autre script python pour générer requirements.txt à partir du fichier Pipfile.lock avec des hachages :
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 Merci ! Votre solution a vraiment fonctionné pour moi.
jq
en utilisant brew install jq
requirements.txt
partir de Pipfile.lock
Il semble que cela puisse être résolu avec le drapeau --keep-outdated
, ou est-ce que je me trompe ?
pipenv lock --keep-outdated -d -r > requirements.txt
PS c'est un drapeau ennuyeux et verbeux pour résoudre ce problème
Malheureusement @jacobisaliveandwell l'indicateur --keep-outdated semble mettre à jour les sous-dépendances : https://github.com/pypa/pipenv/issues/3975
@paytonrules C'est un bug, mais l'esprit du drapeau est toujours la réponse à ce problème.
PS Pas besoin de baisser le pouce pour ça :-(
Je veux juste mentionner qu'à partir des solutions de contournement indiquées, il existe des différences :
pipenv run pip freeze
renvoie les noms de packages sensibles à la casse (par exemple, PyYAML
)
pipenv lock --requirements
renvoie tous les noms de packages en minuscules (par exemple, pyyaml
)
@ Darkless012 , vous devez ouvrir un autre ticket décrivant cela et référencer ce problème comme étant lié.
Pure bash, juste des packages, rien d'autre, au cas où quelqu'un ne pourrait pas ou ne voudrait pas installer jq, juste au cas où cela aiderait quelqu'un,
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
Y a-t-il quelque chose qui copie également les hachages du Pipfile vers requirements.txt (par exemple, quelque chose comme une plate-forme str) pour que pip install --require-hashes
fonctionne ?
$ 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.
Vous pouvez utiliser micropipenv qui peut convertir les fichiers Pipenv.lock (également poet.lock) en requirements.txt (raw requirements.txt ou pip-tools compatible). Voir https://github.com/thoth-station/micropipenv/#micropipenv -requirements--micropipenv-req
Commentaire le plus utile
tu peux courir