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
Gracias Kevin!
Hola!
hay alguna forma de crear un entorno virtual con una versión de python distinta a la que tengo instalada de manera global en mi ordenador?
Sendo Crack, me ahorraste como 25 años con este trucazo
Yo que conozco el package.json de Nodejs me parece una belleza este pipfile.
Mmm es curioso en vez de utilizar python puro para montar con virtual env utilizo conda, me agrado que lo hiciera jajaja 😃
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.
Excelente aporte!! Comparto tu opinion de que pipenv puede ser de mayor utilidad que venv. Un saludo y este tutorial está entre mis favoritos.