Pipenv: Generar requisitos.txt desde Pipfile.lock

Creado en 31 ene. 2019  ·  25Comentarios  ·  Fuente: pypa/pipenv

¿Cómo generar un archivo requirements.txt a partir de Pipfile.lock existente sin bloquear?
Cuando ejecuto pipenv lock -r , ignora los Pipfile.lock existentes y vuelve a realizar el proceso de bloqueo.

Hay una solución para esto:

$ pipenv sync
$ pipenv run pip freeze

En mi situación particular, estoy creando una imagen acoplable y usando requirements.txt en Dockerfile . Me gustaría evitar crear un entorno virtual en la máquina host solo para poder crear requirements.txt .

Comentario más útil

Tu puedes correr

pipenv run pip freeze > requirements.txt

Todos 25 comentarios

Pipenv no proporciona una forma para esto, puede buscar otras bibliotecas de utilidades de pipfile como pipfile-requirements

Tu puedes correr

pipenv run pip freeze > requirements.txt

Tu puedes correr

pipenv run pip freeze > requirements.txt

Eso es lo que mencioné como solución en la primera publicación.

Pero solo funciona si tiene su entorno pipenv sincronizado (todos los paquetes están instalados).
Extraer dependencias directamente de Pipfile.lock es más conveniente para mí:

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

Entrada en el blog
herramienta

LOL, ya he mencionado esa biblioteca.

Personalmente, no me gusta tener una biblioteca dedicada a eso. Además, existe una mayor probabilidad de que un miembro del equipo ya tenga jq o alguna otra herramienta de propósito general instalada.

incluso puedes correr

 pipenv lock --requirements > requirements.txt

No funcionará como esperas, porque, como escribí:

Cuando ejecuto pipenv lock -r , ignora el Pipfile.lock existente y vuelve a realizar el proceso de bloqueo.

En otras palabras, realiza una actualización, que potencialmente puede destruir una distribución. Imagínese, genera requirements.txt para usarlo en Dockerfile para construir una imagen acoplable. Localmente, su aplicación funciona, pero cuando genera requirements.txt usando pipenv lock , los requisitos pueden actualizarse a versiones incompatibles o simplemente rotas (con suerte, es un caso raro). Y no sabrá esto antes de ejecutar la imagen. Por lo tanto, deberá volver a probar la aplicación después de ejecutar pipenv lock .

Si no quieres usar jq , mejor usa el enfoque que propuse en la primera publicación con pipenv sync (que no se actualiza).

@Zebradil su enfoque jq oneliner es mucho más simple que el propio paquete pipfile-requirements de @frostming (más de 100 líneas de código Python) ya que ya instalé jq , no hay otras dependencias requerido, lo cual es genial.

Sin embargo, después de algunas confirmaciones de git, noté la diferencia entre lo que sale pipenv lock --requirements y lo que jq obtiene a través del archivo Pipfile.lock e imprime:

  • La salida jq no tiene -i https://pypi.org/simple como la primera línea, a diferencia de lo que pipenv lock --r siempre inserta como la primera línea.
  • La salida jq no incluye la anotación de los paquetes. Por ejemplo: la salida pipenv lock --r tiene esta línea appnope==0.1.0 ; sys_platform == 'darwin' , pero en la salida jq , es appnope==0.1.0 . Otro ejemplo es pipenv lock -r genera pexpect==4.7.0 ; sys_platform != 'win32' mientras que jq genera pexpect==4.7.0 , no estoy seguro si esto importa o no.
  • el orden del paquete del archivo de requisitos es diferente entre las dos salidas. jq que presumiblemente toma el orden del paquete en el archivo Pipfile.lock , que siempre ordena en orden ascendente en alfabetos y longitud de caracteres, por ejemplo, flask está delante de flask-sqlalchemy o cualquier flask-XXXXX paquetes, mientras que pipenv lock --r genera flask detrás flask-sqlalchemy , que es diferente del orden en Pipfile.lock . Esta es una gran molestia porque no genera una diferencia mínima de git. Consideraría que esto es un error en pipenv .

Hola @ye , buena comparación de los métodos. Podría ayudar a las personas a elegir la solución adecuada para su situación particular y evitar advertencias.

Sí, como dijiste, el enfoque propuesto con jq tiene una funcionalidad limitada. Es posible extenderlo para agregar anotaciones y URL de índice de paquete, pero no necesito esto ahora.

Para evitar tener diferencias en los requisitos generados.txt, se debe considerar usar el mismo enfoque cada vez. De manera similar, el uso de diferentes herramientas de formato de código puede generar resultados inconsistentes. Por lo tanto, no veo un problema aquí.

Tu puedes correr

pipenv run pip freeze > requirements.txt

Eso es lo que mencioné como solución en la primera publicación.

Pero solo funciona si tiene su entorno pipenv sincronizado (todos los paquetes están instalados).
Extraer dependencias directamente de Pipfile.lock es más conveniente para mí:

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

Entrada en el blog
herramienta

Hola,

Gracias por tu solución. Me encontré con el mismo problema, pero también necesito la definición de las fuentes creadas por pipenv lock -r , es decir: -i, --extra-index-url. Esto se debe a que trabajo con fuentes privadas.

@Zebradil Creo que lo mencionaste.

Así que creé otro script mínimo sin dependencias en python que incluye esa funcionalidad. También expande env vars en caso de que tenga sus fuentes definidas de esa manera en su Pipfile.

Si alguien quiere echarle un vistazo lo dejo aquí: https://gist.github.com/rcastill/dab85c234dd10fa7af56755116c75aee

En caso de que ayude a alguien más, aquí se explica cómo incluir los hash en los resultados:

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

Esto crea entradas como

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

Lo que hace que pip haga cumplir los hashes.

Si desea incluir solo los requisitos que estaban en el archivo de requisitos original (siempre que ya estuvieran bloqueados en una versión específica con == ):

 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 es necesario porque los archivos requirements.txt pueden contener nombres de paquetes en mayúsculas y minúsculas, pero pipenv install -r requirements.txt los pone en minúsculas en Pipfile.

Aquí hay una pequeña secuencia de comandos de Python en caso de que desee convertir el Pipfile (no el archivo de bloqueo) en un archivo de requisitos.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 Hola, encontré https://github.com/frostming/pipfile-requirements útil, pero ¿por qué no se integró en pipenv?

@linusguan La herramienta existe para aquellos que no quieren instalar la gran biblioteca pipenv, cuando haya instalado pipenv, puede usar pipenv lock -r

@frostming Lo encuentro bastante útil para usar con otras herramientas que no son compatibles con pipfile.lock.
El problema con pipenv lock -r es que actualiza pipfile.lock, por lo que no puedo usarlo para producir una compilación determinista junto con otras herramientas. Algo como pipenv lock -r --ignore-pipfile sería ideal.

Aquí hay otra secuencia de comandos de python para generar requisitos.txt desde el archivo Pipfile.lock con 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 ¡Gracias! Su solución realmente funcionó para mí.

  • Primero instalo la herramienta jq usando brew install jq
  • Luego usó su script para generar requirements.txt a partir de Pipfile.lock

Parece que esto se puede resolver con la --keep-outdated , ¿o me equivoco?

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

PD, esa es una bandera molestamente detallada para resolver esto

Desafortunadamente , @jacobisaliveandwell , el indicador --keep-outdated parece actualizar las subdependencias: https://github.com/pypa/pipenv/issues/3975

@paytonrules Eso es un error, pero el espíritu de la bandera sigue siendo la respuesta a este problema.

PD No hay necesidad de pulgares hacia abajo para eso :-(

Solo quiero mencionar que de las soluciones alternativas indicadas, hay diferencias:
pipenv run pip freeze devuelve nombres de paquetes que distinguen entre mayúsculas y minúsculas (p. ej. PyYAML )
pipenv lock --requirements devuelve todos los nombres de paquetes en minúsculas (por ejemplo, pyyaml )

@Darkless012 , debe abrir otro ticket que describa eso y hacer referencia a este problema como relacionado.

Puro bash, solo paquetes, nada mas, por si alguien no puede o no quiere instalar jq, por si a alguien le sirve,

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

¿Hay algo que también copie los valores hash del Pipfile a los requisitos.txt (por ejemplo, dado algo como una cadena de plataforma) para que pip install --require-hashes funcione?

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

Puede usar micropipenv que puede convertir archivos Pipenv.lock (también poesía.lock) a requisitos.txt (requisitos sin formato.txt o compatible con pip-tools). Consulte https://github.com/thoth-station/micropipenv/#micropipenv -requirements--micropipenv-req

¿Fue útil esta página
0 / 5 - 0 calificaciones