Platzi
Platzi

¡Invierte en ti y celebremos! Adquiere un plan Expert o Expert+ a precio especial.

Antes:$349
$259
Currency
Antes:$349
Ahorras:$90
COMIENZA AHORA
31

Pipenv: Virtualenv y pip en un solo comando.

Kevin
iKenshu
91957

Uno de los problemas que puede tener Python a la hora de manejar la instalación de paquetes con pip es que si queremos tener varias versiones de la misma librería debemos usar entorno virtuales. Por ejemplo tenemos un proyecto en el que estamos trabajando con la versión de Django 1.11 y tenemos otro con la versión 2.0. Para este tipo de cosas es necesario tener dos entornos virtuales y es donde librerías como virtualenv y virtualenvwrapper nos pueden hacer un poco más fácil el flujo de trabajo.

Otro problema es a la hora de manejar tus archivos requirements.txt ya que al tener algo como esto.

Django==1.11.5django-widget-tweaks==1.4.1djangorestframework==3.6.4olefile==0.44Pillow==4.2.1pytz==2017.2

Es tu responsabilidad estar pendiente de alguna actualización de esas librerías, puede que la versión que tienes en tu archivo tenga un hueco de seguridad que debas actualizar a la brevedad. Lo cierto es que algunas veces, solo estarás pendiente de las importantes como Django o Rest_framework.

Este tipo de problemas, junto con algunos otros son cosas que resuelve Pipenv.

¿Qué es Pipenv?

Pipenv es la herramienta oficial recomendada para el empaquetado por PyPA (Python Packaging Authority) que apunta a traer lo mejor del empaquetado de otros lenguajes, cosas como npm, composer, bundler, cargo, yarn; al mundo de Python. Automáticamente crea entornos virtuales para tus proyectos, así como instalar y desinstalar paquetes de tus archivos Pipfile

¿Pipfile?

Sí, son archivos que buscan reemplazar el requierements.txt, con la sintaxis TOML para declarar todo tipo de dependencias. Un solo archivo Pipfile para reemplazar la variedad de requirements.txt. Ejemplo dev-requirements, test-requirements, etc.

Instalación y uso

Para instalar Pipenv solo debemos hacerlo con pip.

pip install pipenv

Y listo eso es todo. Ahora olvidémonos de pip.

Digamos por ejemplo que tenemos una carpeta llamada Platzi y entramos en ella para crear nuestro entorno virtual

➜  cd platzi
➜  platzi pipenv --three
Creating a virtualenv forthis project…
Using /usr/bin/python3 (3.5.2) to create virtualenv…
⠋Running virtualenv with interpreter /usr/bin/python3
Using base prefix '/usr'New python executable in/home/ikenshu/.local/share/virtualenvs/platzi-K76ZBwFf/bin/python3
Also creating executable in/home/ikenshu/.local/share/virtualenvs/platzi-K76ZBwFf/bin/python
Installing setuptools, pip, wheel...done.

Virtualenv location:/home/ikenshu/.local/share/virtualenvs/platzi-K76ZBwFf
Creating a Pipfile forthis project

pipenv --three esto crea un entorno virtual con la versión tres de python. Podemos pasarle --two en el caso de que queramos usar realmente la versión 2.7. Si tenemos una sola versión, en el caso de usuarios en Windows, podemos usar simplemente pipenv install y va a crear el entorno.

También vemos que al final genera un archivo Pipfile. Instalemos Django.

➜  platzi pipenv install django
Installing django…
Collecting django
  Using cached https://files.pythonhosted.org/packages/23/91/2245462e57798e9251de87c88b2b8f996d10ddcb68206a8a020561ef7bd3/Django-2.0.5-py3-none-any.whl
Collecting pytz (from django)
  Using cached https://files.pythonhosted.org/packages/dc/83/15f7833b70d3e067ca91467ca245bae0f6fe56ddc7451aa0dc5606b120f2/pytz-2018.4-py2.py3-none-any.whl
Installing collected packages: pytz, django
Successfully installed django-2.0.5 pytz-2018.4

Adding django to Pipfile's [packages]…
Pipfile.lock not found, creating…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Updated Pipfile.lock (1adabf)!
Installing dependencies from Pipfile.lock (1adabf)…
  🐍   ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 2/2 — 00:00:01

Perfecto. Ahora tenemos Pipfile y Pipfile.lock, démosle un vistazo a ambos.

Pipfile

[[source]]url = "https://pypi.org/simple"verify_ssl = truename = "pypi"
[dev-packages]
[packages]django = "*"
[requires]python_version = "3.5"

Vemos que esta separado en secciones, como [[source]] que nos muestra el enlace de donde vienen los paquetes. También esta separado con [dev-packages] y [packages] donde esta django que recién instalamos con un asterisco que básicamente se refiere a la última versión y [requires] donde esta la versión de python que estamos usando para el entorno virtual.

Pipfile.lock

{
    "_meta": {
        "hash": {
            "sha256": "6fedc9216775508baa2496b59b7cd7e991827db84bd68be0cada8c472f1adabf"
        },
        "pipfile-spec": 6,
        "requires": {
            "python_version": "3.5"
        },
        "sources": [
            {
                "name": "pypi",
                "url": "https://pypi.org/simple",
                "verify_ssl": true
            }
        ]
    },
    "default": {
        "django": {
            "hashes": [
                "sha256:26b34f4417aa38d895b6b5307177b51bc3f4d53179d8696a5c19dcb50582523c",
                "sha256:71d1a584bb4ad2b4f933d07d02c716755c1394feaac1ce61ce37843ac5401092"
            ],
            "index": "pypi",
            "version": "==2.0.5"
        },
        "pytz": {
            "hashes": [
                "sha256:65ae0c8101309c45772196b21b74c46b2e5d11b6275c45d251b150d5da334555",
                "sha256:c06425302f2cf668f1bba7a0a03f3c1d34d4ebeef2c72003da308b3947c7f749"
            ],
            "version": "==2018.4"
        }
    },
    "develop": {}
}

Este archivo contiene todas las dependencias, pueden notar que pytz esta instalada, pero no se muestra en el Pipfile anterior, ya que es una subdependencia de Django. Pipfile.lock muestra la versión exacta de que cada paquete instalado con sus hashes, los cuales se aseguran de instalar la misma versión cuando estemos en producción, esto nos ahorrará muchos dolores de cabeza.

También esta dividido en dos grupos tanto default y develop. Teniendo separado lo que usamos en desarrollo con lo que necesitamos en producción.

Si queremos instalar un paquete exclusivamente para desarrollo, pasamos --dev como argumento a nuestro comando.

➜  platzi pipenv install django-debug-toolbar --dev
Installing django-debug-toolbar…
Collecting django-debug-toolbar
  ...
Collecting sqlparse>=0.2.0 (from django-debug-toolbar)
  ...
...
Installing collected packages: sqlparse, django-debug-toolbar
Successfully installed django-debug-toolbar-1.9.1 sqlparse-0.2.4Adding django-debug-toolbar to Pipfile's [dev-packages]…
Pipfile.lock (1adabf) out of date, updating to (a07e1e)…
Locking [dev-packages] dependencies…
Updated Pipfile.lock (a07e1e)!
Installing dependencies from Pipfile.lock (a07e1e)…
  🐍   ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 6/6 — 00:00:04

Podemos ver que después de instalar, actualiza de inmediato nuestro archivo Pipfile colocando nuestro paquete en la sección [dev-packages]

...

[dev-packages]
django-debug-toolbar = "*"
... 

El cambio más notable lo podemos ver en el Pipfile.lock, en la sección develop.

"develop": {
        "django": {
            "hashes": [
                "sha256:26b34f4417aa38d895b6b5307177b51bc3f4d53179d8696a5c19dcb50582523c",
                "sha256:71d1a584bb4ad2b4f933d07d02c716755c1394feaac1ce61ce37843ac5401092"
            ],
            "index": "pypi",
            "version": "==2.0.5"
        },
        "django-debug-toolbar": {
            "hashes": [
                "sha256:4af2a4e1e932dadbda197b18585962d4fc20172b4e5a479490bc659fe998864d",
                "sha256:d9ea75659f76d8f1e3eb8f390b47fc5bad0908d949c34a8a3c4c87978eb40a0f"
            ],
            "index": "pypi",
            "version": "==1.9.1"
        },
        "pytz": {
            "hashes": [
                "sha256:65ae0c8101309c45772196b21b74c46b2e5d11b6275c45d251b150d5da334555",
                "sha256:c06425302f2cf668f1bba7a0a03f3c1d34d4ebeef2c72003da308b3947c7f749"
            ],
            "version": "==2018.4"
        },
        "sqlparse": {
            "hashes": [
                "sha256:ce028444cfab83be538752a2ffdb56bc417b7784ff35bb9a3062413717807dec",
                "sha256:d9cf190f51cbb26da0412247dfe4fb5f4098edb73db84e02f9fc21fdca31fed4"
            ],
            "version": "==0.2.4"
        }
    }

Se han instalado más subdependecias que django-debug-toolbar necesita, incluso vemos que esta django. Esto es bastante útil ya que no tenemos que tener archivos requirements separado para las etapas de nuestro producto desarrollo y producción.

Podemos borrar nuestro entorno virtual con pipenv --rm por alguna razón. Y podemos crear otro de nuevo con pipenv install. Inmediatamente va a tomar todo lo que tenemos en nuestros archivos Pipfile y lo creará tomando paquetes y hashes.

Todo esto lo hemos hecho sin activar el entorno virtual que hemos creado, pero para correr los comandos que trae django o flask, podemos hacer pipenv run django-admin [startproject/startapp/etc]. Si queremos activar nuestro entorno virtual podemos hacer pipenv shell

➜  platzi pipenv shell
Spawning environment shell (/bin/bash). Use'exit'to leave.
. /home/ikenshu/.local/share/virtualenvs/platzi-K76ZBwFf/bin/activate
➜  platzi . /home/ikenshu/.local/share/virtualenvs/platzi-K76ZBwFf/bin/activate
(platzi-K76ZBwFf) ➜  platzi

Notarán que el nombre del entorno virtual es el mismo que la carpeta donde estamos con números al azar.

Para desinstalar un paquete puedes hacerlo, como creo que sabes, con uninstall

pipenv uninstall django

o puedes eliminar todos los paquetes

pipenv uninstall--all

Comandos Extras

Algunas cosas interesantes de pipenv, son por ejemplo:

pipenv check

Esto verificará si nuestro entorno tiene algunas vulnerabilidades y requisitos PEP 508

pipenv graph

Nos muestra un árbol de los paquetes instalados con sus respectivas subdependecias.

pipenv --venv

Podemos ver la ruta donde se encuentra nuestro entorno virtual, algo como /home/ikenshu/.local/share/virtualenvs/platzi-K76ZBwFf

pipenv --where

Nos muestra la ruta donde tenemos nuestro proyecto.

Tengo un requirements.txt ¿Lo puedo usar?

Sí, puedes instalar las dependencias que tengas en ese archivo con pipenv y convertir todo eso a un archivo Pipfile. De hecho si tienes el archivo en el proyecto y corres pipenv install va a tomarlo y te saldrá algo como esto.

requirements.txt found, instead of Pipfile! Converting…
Warning: Your Pipfile now contains pinned versions, if your requirements.txt did.
We recommend updating your Pipfile to specify the"*"version, instead.

Puedes usar el mismo -r que pip

pipenv install -r requirements.txt

Si tienes un requirements exclusivo para desarrollo también lo puedes instalar, para que se agregue en la sección adecuada de nuestro Pipfile.

pipenv install -r requirements.txt --dev

De la misma manera puedes generar archivos requirements desde Pipfile.

pipenv lock -r > requirements.txt
pipenv lock -r -d > dev-requirements.txt

Conclusión

Me parece que Pipenv nos hace la vida más sencilla a la hora de manejar entorno virtuales, nos ahorra tiempo. Ya que pasamos de cosas como crear el entorno virtual, activarlo, instalar paquetes.

De esto:

cd ~/virtualenvs
python -m virtualenv create myproject
./source/bin/activate.sh 
pip install -r requirements.txt 
deactivate
cd ~/code/myproject

a esto

cd ~/code/myproject  
pipenv install

Vale la pena darle un vistazo y hacer algunas pruebas con él, ver como funciona para tu flujo de trabajo.

Cuéntame en los comentarios que te ha parecido este tutorial y si vas a probar lo nuevo de pipenv. SI tienes alguna duda estaré encantado de ayudar.

Links de interes:
Documentación Pipenv
Charla en PyCon 2018

Escribe tu comentario
+ 2
Ordenar por:
2
1464Puntos

Kevin, esta excelente! Necesito más de tu sabiduría, gracias por el tremendo aporte. Seguiré investigando para saber como manejar estos entornos virtuales.

2
91957Puntos
3 años

Gracias, espero seguir compartiendo cosas. Puedes mirar la charla que deje al final para saber un poco más, yo lo he estado probando y funciona bastante bien.

1
3890Puntos

¡Excelente material sigue así crack!.

1
5042Puntos

Mmm es curioso en vez de utilizar python puro para montar con virtual env utilizo conda, me agrado que lo hiciera jajaja 😃

1

Muy buen material de ayuda muchas gracias, ahora veo que toma mucho de node.js, no es así?? Veo mucha similitud, con el package.json.

1
12583Puntos

Yo que conozco el package.json de Nodejs me parece una belleza este pipfile.

0
10050Puntos

Excelente aporte!! Comparto tu opinion de que pipenv puede ser de mayor utilidad que venv. Un saludo y este tutorial está entre mis favoritos.