Pipenv: Générer requirements.txt à partir de Pipfile.lock

Créé le 31 janv. 2019  ·  25Commentaires  ·  Source: pypa/pipenv

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 .

Commentaire le plus utile

tu peux courir

pipenv run pip freeze > requirements.txt

Tous les 25 commentaires

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

Article de blog
outil jq

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 ignore Pipfile.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 :

  • La sortie 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.
  • La sortie 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.
  • l'ordre des packages du fichier requirements est différent entre les deux sorties. 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 de Pipfile.lock est plus pratique pour moi :

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

Article de blog
outil jq

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.

  • J'installe d'abord l'outil jq en utilisant brew install jq
  • Ensuite, utilisez votre script pour générer 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

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

erinxocon picture erinxocon  ·  3Commentaires

leileigong picture leileigong  ·  3Commentaires

bgjelstrup picture bgjelstrup  ·  3Commentaires

jakul picture jakul  ·  3Commentaires

AkiraSama picture AkiraSama  ·  3Commentaires