Pipenv: gestión de dependencias en Python para dormir tranquilos

Publicado por Alejandro Escario en

Uno de los puntos débiles de muchos lenguajes de programación es que no incluyen sistemas de gestión de dependencias y proyectos. Al menos no desde el momento de su creación o como herramienta oficial. Esto dificulta enormemente el desarrollo de proyectos grandes, y multi-módulo.

Para solucionar esto, cada lenguaje cuenta con distintas soluciones oficiales y no oficiales que ayudan en esta gestión.

En el caso de Python (igual que pasa en PHP con composer y otros sistemas similares) tenemos la posibilidad de gestionar las dependencias de distintas maneras:

  • Dependencias instaladas de forma global.
  • Dependencias instaladas en un entorno virtual.

En este artículo nos vamos a centrar en abordar el manejo de dependencias con la segunda opción. Ésta variante, a su vez puede llevarse a cabo de distintas formas.

La más directa consiste en trabajar directamente con pip, los ficheros de dependencias requeridas, etc. Sin embargo, un proceso que parece muy sencillo a simple vista, se puede acabar dificultando al trabajar con proyectos grandes o muy grandes o, incluso, multimódulo.

Para evitar que nos suceda esto, hay herramientas basadas en los mismos conceptos (e incluso las mismas herramientas) pero con un flujo de trabajo más controlado y bien definido. Permitiendo controlar mucho mejor las dependencias, aislando correctamente todas aquellas necesarias y excluyendo las innecesarias, etc.

En este artículo vamos a adentrarnos en el mundo de Pipenv.

Logo de Pipenv

Pipenv es una herramienta que tiene por objetivo facilitar el manejo de entornos virtuales, así como facilitar el proceso de gestión de dependencias y paquetes. Vamos a hacer un recorrido de la herramienta que nos permita descubrir parte del potencial de la herramienta.

Instalación

El presente artículo asume que estamos usando Python 3. Si no estamos seguros de la versión que tenemos instalada, podemos ejecutar el siguiente comando:

➜  python --version
Python 3.9.1

Teniendo en cuenta todo esto, vamos a ponernos manos a la obra y a instalar el paquete pipenv. Tenemos varias opciones:

Mac OsX

Podemos hacer uso de hombrew para instalar fácilmente pipenv

➜  brew install pipenv
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 4 taps (microsoft/mssql-release, homebrew/core, homebrew/cask and homebrew/services).
==> New Formulae
apt                                                   docuum                                                mailcatcher                                           pari-seadata-big
aws-vault                                             eigenpy                                               microsoft/mssql-release/msodbcsql17@17.8.1.1          procps
basis_universal                                       fanyi                                                 microsoft/mssql-release/mssql-tools@17.8.1.1          pyoxidizer
bubblewrap                                            firefoxpwa                                            newrelic-infra-agent                                  reproc
bupstash                                              fst                                                   notcurses                                             rsc_2fa
cargo-bloat                                           ghostunnel                                            onedrive                                              singularity
cargo-llvm-lines                                      h2c                                                   opensearch-dashboards                                 spot
cargo-outdated                                        i2c-tools                                             ots                                                   sql-lint
chrpath                                               influxdb-cli                                          pari-elldata                                          stylua
cilium-cli                                            joplin-cli                                            pari-galdata                                          wildmidi
cruft                                                 kn                                                    pari-galpol                                           xauth
datree                                                libaec                                                pari-seadata                                          xsel
==> Updated Formulae
Updated 2099 formulae.
==> Renamed Formulae
prestosql -> trino
==> Deleted Formulae
giter8                                                procyon-decompiler                                    terraform-provisioner-ansible                         tj
==> New Casks
betterdiscord-installer    clock-signal               gosign                     leapp                      mimestream                 stork                      trezor-suite               wifi-explorer-pro
blackhole-64ch             duplicate-file-finder      infra                      maccleaner-pro             mweb-pro                   temurin                    vsd-viewer                 wing-personal
blockbench                 fluent-reader              jiohome                    memory-cleaner             open-video-downloader      touch-portal               vsdx-annotator             zebra2
clay                       foxglove-studio            kdocs                      midi-router-client         shottr                     transfer                   vym
==> Updated Casks
Updated 890 casks.
==> Deleted Casks
3cxphone                                   elpki                                      lightwright                                phonetrans                                 superbeam
agfeo-dashboard                            finisher-fluxx                             locklizard-safeguard-viewer                playnow                                    tbs-studio
anytrans                                   finisher-micro                             macclean                                   plecs-standalone                           thetube
anytrans-for-android                       finisher-neo                               macintosh-explorer                         pomolectron                                trufont
axe-electrum                               flow-e                                     modulair                                   privatus                                   uberconference
baiducloud                                 fluxcenter                                 mweb                                       pro-fit                                    unity-appletv-support-for-editor
boonzi                                     fm3-edit                                   noraswitch                                 qtum                                       unity-linux-il2cpp-support-for-editor
brooklite                                  imarisviewer                               obyte                                      qyooo                                      unity-macos-il2cpp-support-for-editor
colormunki-photo                           imobie-m1-app-checker                      open-ecard                                 rubitrack-pro                              utox
deadbeef                                   instant-articles-builder                   otter-browser                              s3stat-setup                               wanna
dnagedcom                                  instasizer                                 pastor                                     scrooo                                     wingpersonal
dragthing                                  jabt-flow                                  phonebrowse                                simplelink-msp432e4-sdk                    wolfram-player
dukto                                      jidusm                                     phoneclean                                 spectrum                                   youtube-dl-gui
eaccess                                    lektor                                     phonerescue                                stageplotpro                               zbuc-imgur

==> Downloading https://ghcr.io/v2/homebrew/core/pipenv/manifests/2021.5.29
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/pipenv/blobs/sha256:3e01446c114bb70d72f7455b19417e9e3190a95dcd565dc4ce994988b1b49f54
==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:3e01446c114bb70d72f7455b19417e9e3190a95dcd565dc4ce994988b1b49f54?se=2021-08-25T22%3A30%3A00Z&sig=RwjOht74WcGb6QyObhAXlWI%2F31JHBb
######################################################################## 100.0%
==> Pouring pipenv--2021.5.29.big_sur.bottle.tar.gz
==> Caveats
zsh completions have been installed to:
  /usr/local/share/zsh/site-functions
==> Summary
🍺  /usr/local/Cellar/pipenv/2021.5.29: 1,854 files, 28.2MB
==> `brew cleanup` has not been run in 30 days, running now...
...
Pruned 2 symbolic links and 19 directories from /usr/local

Otros

Para dar soporte a cualquier plataforma, ya sea de las anteriormente mencionadas o cualquier otra, podemos hacer uso del paquete pip o pip3. Por ello, lo primero que tenemos que hacer es comprobar que tenemos instalado el gestor de paquetes pip en el equipo, para lo que ejecutaremos el comando pip o pip3:

➜  pip3 --version
pip 20.2.3 from /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pip (python 3.9)

Para posteriormente instalar el gestor de paquetes.

➜  pip3 install pipenv
Collecting pipenv
  Using cached pipenv-2021.5.29-py2.py3-none-any.whl (3.9 MB)
Requirement already satisfied: virtualenv in /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages (from pipenv) (20.7.2)
Requirement already satisfied: virtualenv-clone>=0.2.5 in /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages (from pipenv) (0.5.6)
Requirement already satisfied: setuptools>=36.2.1 in /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages (from pipenv) (49.2.1)
Requirement already satisfied: pip>=18.0 in /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages (from pipenv) (20.2.3)
Requirement already satisfied: certifi in /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages (from pipenv) (2021.5.30)
Requirement already satisfied: distlib<1,>=0.3.1 in /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages (from virtualenv->pipenv) (0.3.2)
Requirement already satisfied: filelock<4,>=3.0.0 in /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages (from virtualenv->pipenv) (3.0.12)
Requirement already satisfied: six<2,>=1.9.0 in /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages (from virtualenv->pipenv) (1.16.0)
Requirement already satisfied: backports.entry-points-selectable>=1.0.4 in /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages (from virtualenv->pipenv) (1.1.0)
Requirement already satisfied: platformdirs<3,>=2 in /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages (from virtualenv->pipenv) (2.2.0)
Installing collected packages: pipenv
Successfully installed pipenv-2021.5.29
WARNING: You are using pip version 20.2.3; however, version 21.2.4 is available.
You should consider upgrading via the '/Library/Frameworks/Python.framework/Versions/3.9/bin/python3.9 -m pip install --upgrade pip' command.

Una vez instalado podremos comprobar la versión ejecutando:

➜   pipenv --version
pipenv, version 2021.5.29

Conceptos básicos

Como hemos dicho anteriormente Pipenv es un gestor de dependencias en entornos virtuales que facilita mucho el proceso de gestión del proyecto y, sobre todo, permite que un equipo trabaje con las mismas versiones de las dependencias y un ecosistema lo más parecido posible aunque se usen distintos equipos y configuraciones base.

Para ello, Pipenv se apoya en una serie de ficheros:

Pipfile

Este fichero contiene información básica del proyecto, así como las dependencias del mismo. Más adelante, veremos un ejemplo

Pipfile.lock

Fichero que complementa a Pipfile. Si bien este último permite identificar versiones genéricas de las librerías y otra información relevante, el fichero Pipfile.lock nos permite describir la configuración exacta del proyecto. Es decir, si en el primero decimos que queremos un paquete concreto en su versión 2, en el fichero Pipfile.lock queda definida la versión exacta de dicho paquete. Esto permite facilitar enormemente el flujo de trabajo de equipos de cualquier tamaño.

Crear un proyecto con Pipenv

Crear. unproyecto con Pipenv es muy sencillo. Para ello ejecutaremos el comando con el argumento –three para python 3 y –two para python 2

➜  pipenv --three
Creating a virtualenv for this project...
Pipfile: /Users/alejandro/workspace/python/Pipfile
Using /opt/local/bin/python3.9 (3.9.5) to create virtualenv...
⠇ Creating virtual environment...created virtual environment CPython3.9.5.final.0-64 in 471ms
  creator CPython3Posix(dest=/Users/alejandro/.local/share/virtualenvs/python-8t82TBKP, clear=False, no_vcs_ignore=False, global=False)
  seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/Users/alejandro/Library/Application Support/virtualenv)
    added seed packages: pip==21.2.3, setuptools==57.4.0, wheel==0.37.0
  activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator

&#x2714; Successfully created virtual environment!
Virtualenv location: /Users/alejandro/.local/share/virtualenvs/python-8t82TBKP
Creating a Pipfile for this project...

Este comando ha creado el fichero Pipfile que hemos comentado anteriormente y que tendrá un contenido similar a:

[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]

[dev-packages]

[requires]
python_version = "3.9"

En este documento tenemos la definición del proyecto, los paquetes y paquetes de desarrollo necesarios para ejecutar nuestro proyecto y los elementos requeridos. De momento el fichero es muy simple. No obstante, poco a poco iremos viendo como crece y varía con los comandos que iremos ejecutando.

Nuestro primer script

Vamos a crear un script que obtenga el precio del bitcoin haciendo uso de la API pública de Coindesk: https://api.coindesk.com/v1/bpi/currentprice.json

Primero vamos a importar la librería necesaria para poder hacer peticiones HTTP:

➜  pipenv install requests
Installing requests...
Adding requests to Pipfile's [packages]...
&#x2714; Installation Succeeded
Pipfile.lock not found, creating...
Locking [dev-packages] dependencies...
Locking [packages] dependencies...
Building requirements...
Resolving dependencies...
&#x2714; Success!
Updated Pipfile.lock (fe5a22)!
Installing dependencies from Pipfile.lock (fe5a22)...
  &#x1f40d;   ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 0/0 — 00:00:00
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.

Perfecto, ya tenemos instalado el paquete requests. En este punto veremos que el fichero Pipfile tiene ahora el paquete que hemos indicado:

[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
requests = "*"

[dev-packages]

[requires]
python_version = "3.9"

Y que ha aparecido un fichero llamado Pipfile.lock que contiene el detalle de las dependencias y las versiones:

{
    "_meta": {
        "hash": {
            "sha256": "b8c2e1580c53e383cfe4254c1f16560b855d984fde8b2beb3bf6ee8fc2fe5a22"
        },
        "pipfile-spec": 6,
        "requires": {
            "python_version": "3.9"
        },
        "sources": [
            {
                "name": "pypi",
                "url": "https://pypi.org/simple",
                "verify_ssl": true
            }
        ]
    },
    "default": {
        "certifi": {
            "hashes": [
                "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee",
                "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"
            ],
            "version": "==2021.5.30"
        },
        "charset-normalizer": {
            "hashes": [
                "sha256:0c8911edd15d19223366a194a513099a302055a962bca2cec0f54b8b63175d8b",
                "sha256:f23667ebe1084be45f6ae0538e4a5a865206544097e4e8bbcacf42cd02a348f3"
            ],
            "markers": "python_version >= '3'",
            "version": "==2.0.4"
        },
        "idna": {
            "hashes": [
                "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
                "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
            ],
            "markers": "python_version >= '3'",
            "version": "==3.2"
        },
        "requests": {
            "hashes": [
                "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24",
                "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"
            ],
            "index": "pypi",
            "version": "==2.26.0"
        },
        "urllib3": {
            "hashes": [
                "sha256:39fb8672126159acb139a7718dd10806104dec1e2f0f6c88aab05d17df10c8d4",
                "sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f"
            ],
            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'",
            "version": "==1.26.6"
        }
    },
    "develop": {}
}

Como hemos comentado anteriormente, este fichero permitirá asegurarnos de que todos los miembros del equipo contamos con las mismas versiones de los paquetes.

Muy bien, ¿pero dónde está el entorno virtual con las dependencias instaladas? Es posible que hayas usado antes pip o los venv y te sorprenderá no ver la típica carpeta env o venv. Para ver su localización ejecutaremos el siguiente comando:

➜  pipenv --venv
/Users/alejandro/.local/share/virtualenvs/python-8t82TBKP

Esto es así porque no tenemos habilitada la opción de generar la carpeta venv en el proyecto, sino que la crea fuera.

➜  export PIPENV_VENV_IN_PROJECT="enabled"

Ambas opciones son válidas. Si una vez habilitada esta variable de entorno volvemos a ejecutar el comando de vgeneración del proyecto, veremos qyue tenemos una carpeta llamada .venv.

➜  pipenv --three
Creating a virtualenv for this project...
Pipfile: /Users/alejandro/workspace/python/Pipfile
Using /opt/local/bin/python3.9 (3.9.5) to create virtualenv...
⠹ Creating virtual environment...created virtual environment CPython3.9.5.final.0-64 in 730ms
  creator CPython3Posix(dest=/Users/alejandro/workspace/python/.venv, clear=False, no_vcs_ignore=False, global=False)
  seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/Users/alejandro/Library/Application Support/virtualenv)
    added seed packages: pip==21.2.3, setuptools==57.4.0, wheel==0.37.0
  activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator

&#x2714; Successfully created virtual environment!
Virtualenv location: /Users/alejandro/workspace/python/.venv
➜  ls -la
total 16
drwxr-xr-x     5 alejandro  staff    160 26 ago 01:05 .
drwx------@ 1344 alejandro  staff  43008 25 ago 23:56 ..
drwxr-xr-x     7 alejandro  staff    224 26 ago 01:05 .venv
-rw-r--r--     1 alejandro  staff    153 26 ago 00:51 Pipfile
-rw-r--r--     1 alejandro  staff   2147 26 ago 00:52 Pipfile.lock

Activar el entorno virutal es tan sencillo como ejecutar el comando:

➜  pipenv shell
Launching subshell in virtual environment...
 . /Users/alejandro/.local/share/virtualenvs/crawler-JJA5iozN/bin/activate
➜  . /Users/alejandro/.local/share/virtualenvs/crawler-JJA5iozN/bin/activate
(python) ➜  

El hecho de que aparezca un nombre enter paréntesis antes del prompt quiere decir que estamos dentro del entorno virtual.

Si queremos crear el entorno virtual a partir de un proyecto descargado de un repositorio, bastaría con ejecutar el comando:

pip install

El primer programa

import requests

response = requests.get('https://api.coindesk.com/v1/bpi/currentprice.json')
json = response.json()

print(f"{json['bpi']['USD']['rate']} @ {json['time']['updated']}")

Y si ahora lo ejecutamos obtendremos la siguiente salida:

(python) ➜ python test.py
49,033.6041 @ Aug 25, 2021 23:19:00 UTC

Con este pequeño ejemplo hemos hecho un recorrido completo en el que se expone el manejo. deproyectos y dependencias con Pipenv. No obstante, es una herramienta con muchas más posibilidades de las que hemos podido ver en el artículo.

Os dejo un link a una página en la que podéis ver más información: Pipenv: Flujo de trabajo en Python para humanos. — documentación de pipenv – 2018.05.18 (pipenv-es.readthedocs.io).

Otra opción es ejecutar el comando pipenv –man. Este comando mostrará en consola la documentación completa del comando con detalles de su uso y sus opciones.

Categorías: Programación

0 comentarios

Deja una respuesta

Marcador de posición del avatar

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *