Hace rato que quería escribir esta entrada. Desde que empecé a usar Python uso virtualenv y pip para manejar los entornos virtuales. Pero al leer Django for Professionals me enteré de que existía una herramienta mejor que pip y virtualenv, llamada Pipenv (no se complicaron mucho con el nombre). Pipenv tiene características que la hacen mucho más robusta y sencilla de utilizar que virtualenv. En este tutorial de Pipenv paso a paso, te voy a explicar la instalación, uso, manejo de archivos y comandos básicos de esta herramienta.
Primero, si ya has oído hablar de los entornos virtuales pero no sabes para que sirven dale una leída a esta entrada. Por otro lado, si el nombre de virtualenv te suena medio esotérico dale una revisada a esta entrada y te lo explico.
Pipenv vs virtualenv
Seguramente ya sabes que pip es usado para manejar paquetes, pero generalmente deseamos tener los paquetes de cada una de nuestras aplicaciones aislados del resto del sistema, por lo que normalmente lo combinamos con virtualenv.
Pip y virtualenv se usan en conjunto para mantener las dependencias de un entorno virtual, pero pip puede llegar a producir entornos diferentes, incluso con un mismo archivo requirements.txt, esto es algo que queremos evitar. El creador de pipenv diseño su herramienta intentando resolver esa problemática.
Pipenv se encarga de unir a pip y a virtualenv en una sola herramienta, además de asegurarse de que el archivo donde se listan las dependencias que se generan produzca exactamente la misma configuración de paquetes, pipenv también permite cargar archivos variables de entorno directamente a partir de archivos .env que se encuentren en la carpeta de trabajo donde nos encontremos.
Instalación y uso de pipenv
Si estás en Debian o alguna distribución derivada (como Ubuntu) puedes probar suerte intentando instalarlo directamente de los repositorios.
sudo apt install pipenv
Si no se encuentra en los repositorios también podemos hacer uso de pip, que ya viene instalado en la mayoría de las distribuciones.
sudo pip install pipenv
Una vez instalado podemos empezar a instalar paquetes usando la opción install, para este ejemplo probemos con una versión específica de Django.
pipenv install django===3.0.1
Si hacemos un ls podremos notar que se nos crearon dos archivos Pipfile y Pipfile.lock.
ls
Pipfile Pipfile.lock
¿Qué tienen estos archivos? Te lo explico a continuación. Primero vamos con el archivo Pipfile.
Pipfile
Empecemos viendo el contenido del archivo Pipfile. Si tienes alguna dificultado con el uso de la linea de comandos te sugiero revisar las entradas donde hablo de los comandos más comunes de GNU/Linux.
cat Pipfile
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
[packages]
django = "===3.0.1"
[requires]
python_version = "3.7"
Analizando el contenido apreciamos este archivo nos muestra varias categorias
- source: la fuente de nuestros paquetes, con su nombre, url y si se usó encripción
- dev-packages: los paquetes de desarrollo, en este momento se encuentra vacio
- packages: los paquetes que hemos instalado y que se usarán en el proyecto
- requires: la versión de Python requerida para el proyecto, se especifica automáticamente o puedes hacerlo tu mismo
pipenv install --dev pytest
Si hacemos un cat nuevamente veremos que debajo de la sección [dev-packages] ya nos aparece pytest como una dependencia.
cat Pipfile
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
pytest = "*"
[packages]
django = "===3.0.1"
[requires]
python_version = "3.7"
Pipfile.lock
Ahora hagamos un cat a Pipfile.lock
cat Pipfile.lock
{
"_meta": {
"hash": {
"sha256": "c2bf0d0008c675fc08df79a9cdb6b94773be0defa60d2c5b8aae0142358aa574"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.7"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"asgiref": {
"hashes": [
"sha256:7e51911ee147dd685c3c8b805c0ad0cb58d360987b56953878f8c06d2d1c6f1a",
"sha256:9fc6fb5d39b8af147ba40765234fa822b39818b12cc80b35ad9b0cef3a476aed"
],
"markers": "python_version >= '3.5'",
"version": "==3.2.10"
},
"django": {
"hashes": [
"sha256:315b11ea265dd15348d47f2cbb044ef71da2018f6e582fed875c889758e6f844",
"sha256:b61295749be7e1c42467c55bcabdaee9fbe9496fdf9ed2e22cef44d9de2ff953"
],
"index": "pypi",
"version": "===3.0.1"
},
...
El archivo puede parecer muy apantallante, pero son únicamente los hashes de los paquetes que instalamos, así como sus dependencias, de esta manera nos aseguramos de que las versiones que instalamos sean las correctas y además nos permitirá obtener exactamente la misma configuración de paquetes si tomamos estos archivos y los llevamos a otra computadora.
¿Cómo visualizar las dependencias de manera gráfica?
Si ahora usamos el comando pipenv graph nos generará una representación detallada y visualmente amigable de las dependencias que tenemos instaladas
pipenv graph
Django==3.0.1
- asgiref [required: ~=3.2, installed: 3.2.10]
- pytz [required: Any, installed: 2020.1]
- sqlparse [required: >=0.2.2, installed: 0.3.1]
pytest==5.4.3
- attrs [required: >=17.4.0, installed: 19.3.0]
- importlib-metadata [required: >=0.12, installed: 1.7.0]
- zipp [required: >=0.5, installed: 3.1.0]
- more-itertools [required: >=4.0.0, installed: 8.4.0]
- packaging [required: Any, installed: 20.4]
- pyparsing [required: >=2.0.2, installed: 2.4.7]
- six [required: Any, installed: 1.15.0]
- pluggy [required: >=0.12,<1.0, installed: 0.13.1]
- importlib-metadata [required: >=0.12, installed: 1.7.0]
- zipp [required: >=0.5, installed: 3.1.0]
- py [required: >=1.5.0, installed: 1.9.0]
- wcwidth [required: Any, installed: 0.2.5]
Generar un archivo Pipfile.lock
También podemos generar un archivo Pipfile.lock a partir de un archivo Pipfile. Borremos el archivo Pipfile.lock y generemos uno nuevo
rm Pipfile.lock
Ahora ejecutemos el comando pipenv lock
pipenv lock
Locking [dev-packages] dependencies…
Building requirements...
Resolving dependencies...
✔ Success!
Locking [packages] dependencies…
Building requirements...
Resolving dependencies...
✔ Success!
Updated Pipfile.lock (88888)!
Al terminar el proceso tendremos nuevamente nuestro archivo Pipfile.lock en la misma carpeta
Encontrar un entorno virtual con pipenv
Todo bien hasta este momento, pero aún no estamos dentro de nuestro entorno virtual, es más, solamente tenemos los archivos Pipfile y Pipfile.lock en nuestra carpeta actual. ¿Y el entorno virtual? Bueno, pipenv coloca el entorno virtual en otra ubicación, para averiguarla podemos usar la opción --venv
pipenv --venv
/home/usuario/.local/share/virtualenvs/proyecto-HHqROqC2
Y ahora, en lugar de localizar el archivo activate manualmente en la ruta anterior, como hacíamos con virtualenv, podemos activar el entorno virtual usando el comando pipenv shell y esto se hará por nosotros automáticamente
pipenv shell
De igual manera que con virtualenv podemos apreciar que el prompt cambiará, indicándonos que estamos dentro del entorno virtual
Variables de entorno con Pipenv
Una de las características que hacen diferente a pipenv es que te permite cargar variables de entorno directamente a partir de un archivo .env cuando entramos en un entorno virtual. Salgamos del entorno virtual un momento para crear el archivo y cargar variables de entorno.
exit
Ahora que el prompt regresó a la normalidad, crearemos un archivo .env con variables de entorno. Lo haré en un solo paso usando el comando echo y redirigiendo el resultado al archivo, pero si te sientes más cómodo usando el comando touch y luego abriéndolo para agregar el contenido también puedes hacerlo y es correcto.
echo "SPAM=eggs" > .env
Si hacemos un ls podremos ver que ahora tenemos nuestro archivo .env en la misma carpeta que están Pipfile y Pipfile.lock
ls -a
. .. .env Pipfile Pipfile.lock
Ahora volvamos a cargar nuestro entorno virtual
pipenv shell
Loading .env environment variables…
Launching subshell in virtual environment…
. /home/usuario/.local/share/virtualenvs/proyecto-HHqROqC2/bin/activate
El prompt cambiará nuevamente, y, si ejecutamos el comando printenv podemos ver que nuestra variable de entorno se agregó perfectamente.
printenv
...
SPAM=eggs
...
Desinstalar paquetes en pipenv
Para desinstalar paquetes usaremos el comando pipenv uninstall y el nombre del paquete.
pipenv uninstall pytest
Uninstalling pytest…
Found existing installation: pytest 5.4.3
Uninstalling pytest-5.4.3:
Successfully uninstalled pytest-5.4.3
Removing pytest from Pipfile…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Building requirements...
Resolving dependencies...
✔ Success!
Updated Pipfile.lock (3f348b)!
Si queremos desinstalar todos los paquetes y dejar nuestro entorno como nuevo podemos usar la opción --all en lugar de especificar un nombre de paquete. Esto borrará todos los archivos del entorno virtual pero dejará el Pipfile completamente a salvo.
pipenv uninstall --all
Un-installing all [dev-packages] and [packages]…
Found 13 installed package(s), purging…
...
Environment now purged and fresh!
Si usamos la opción --all-dev eliminará todas las dependencias de desarrollo, tanto como del entorno virtual como de nuestro Pipfile
pipenv uninstall --all-dev
Un-installing [dev-packages]…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Building requirements...
Resolving dependencies...
✔ Success!
Updated Pipfile.lock (65a03c)!
Ejecutar comandos en entorno virtual con pipenv
También podemos ejecutar comandos directamente en el entorno virtual sin estar dentro. Salte del entorno virtual si estás dentro y asegurate de que el prompt haya regresado a la normalidad antes de ejecutar el siguiente comando.
pipenv run pip install requests
Loading .env environment variables…
Collecting requests
Downloading requests-2.24.0-py2.py3-none-any.whl (61 kB)
|████████████████████████████████| 61 kB 53 kB/s
Collecting idna<3,>=2.5
Downloading idna-2.10-py2.py3-none-any.whl (58 kB)
|████████████████████████████████| 58 kB 641 kB/s
Collecting chardet<4,>=3.0.2
Using cached chardet-3.0.4-py2.py3-none-any.whl (133 kB)
Collecting certifi>=2017.4.17
Downloading certifi-2020.6.20-py2.py3-none-any.whl (156 kB)
|████████████████████████████████| 156 kB 6.1 MB/s
Collecting urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1
Using cached urllib3-1.25.9-py2.py3-none-any.whl (126 kB)
Installing collected packages: idna, chardet, certifi, urllib3, requests
Successfully installed certifi-2020.6.20 chardet-3.0.4 idna-2.10 requests-2.24.0 urllib3-1.25.9
El comando anterior nos dejó con el paquete requests y sus dependencias instaladas en nuestro entorno virtual, sin embargo el archivo Pipfile y Pipfile.lock no se actualizaron. Para borrar todos aquellos paquetes instalados que no se encuentren en los dos archivos anteriores existe pipenv clean.
Limpiar nuestro entorno virtual en pipenv
También podemos limpiar nuestro entorno virtual de todos aquellos paquetes que no estén especificados dentro de nuestro archivo Pipfile.lock usando clean.
pipenv clean
Uninstalling urllib3…
Uninstalling idna…
Uninstalling requests…
Uninstalling chardet…
Uninstalling certifi…
Listo, nuestro entorno no contiene ningún paquete instalado, sin embargo aún existe.
Borrar un entorno virtual en pipenv
Para borrar un entorno virtual usaremos la opción --rm seguida del comando pipenv. Nota que pipenv detectará el entorno virtual a remover extrayendo la información de la carpeta donde nos encontremos, por lo que asegúrate dos veces que estás en la carpeta correcta.
pipenv --rm
Removing virtualenv (/home/usuario/.local/share/virtualenvs/prueba-HHqROqC2)…
El entorno virtual ha quedado eliminado completamente.
Si quieres conocer más funciones de pipenv puedes visitar su documentación oficial.
Si te gustó esta entrada sígueme en Twitter, publico un tweet cada que tengo una nueva entrada. Además Twitteo frecuentemente información interesante sobre tecnología que puede servirte.
Top comments (2)
Muy buen artículo. Muchas gracias. Muy util.
Tengo una duda, ¿sabes que me pasa, por favor?: trabajo en dos macs. He creado un entorno con pipenv y trabajo perfectamente con el pero hago una copia del entorno en un USB para trabajar con el otro mac y no hay forma de activarlo.
La hice usado virtualenv 'entorno' -p python3.10 para tener todo el entono en bajo una carpeta.
Uso Visual Studio Code.
¿sabes como puedo exportar un entorno?
No sé si te entendí correctamente, pero no copies directamente el entorno virtual. Solo copia los pipfiles y pipfile.lock y corre pipenv install en la usb. Es mejor no exportar el entorno, sino solo guardar los Pipfiles y reinstalar todo nuevamente.