Una introducción (breve) a la gestión de dependencias en Python
Lucian Irsigler
14 de septiembre de 2021
0 minutos de lecturaPython se considera un lenguaje «simple»: es fácil de usar y de crear scripts para realizar numerosas tareas, desde extraer datos de sitios web y automatizar procesos hasta crear aplicaciones web a gran escala e incluso hacer ciencia de datos. Sin embargo, las dependencias se gestionan de manera bastante diferente en Python que en otros lenguajes, y la gran cantidad de opciones para configurar entornos y administradores de paquetes solo aumenta la confusión. En esta publicación, veremos distintas formas de gestionar las dependencias en Python y exploraremos brevemente la seguridad de las dependencias.
Python como lenguaje interpretado
Un lenguaje interpretado significa que el script no se traduce a código máquina ni siquiera a un ejecutable. En cambio, se procesa mediante otro programa —en este caso, el intérprete de Python— que ejecuta el código.
Si escribo un script sencillo en Python como este:
Y luego lo ejecuto así:
Obtenemos este resultado:
¿Notaste que en la carpeta donde se ejecutó este código no hay archivos ejecutables, como .exe? Esto se debe a que el ejecutable de Python compila y ejecuta el archivo durante la ejecución, no de antemano.
El truco es que hay un archivo .exe que ejecuta el código de Python. Main.py se procesa mediante ese .exe y luego se ejecuta. Ese archivo .exe es el intérprete de Python compilado que está disponible en la ruta de tu entorno.

Qué es una dependencia en Python
Una dependencia en Python es igual que en cualquier otro lenguaje: una biblioteca de código necesaria para ejecutar el código fuente del script que la importó.
Por ejemplo, si quieres interactuar con una base de datos PostgreSQL, tienes dos opciones: escribir todas las funciones por tu cuenta o instalar el paquete postgres, que ya incluye las consultas y otras capacidades que necesitas.
Entonces, ¿cómo instalarías el paquete de PostgreSQL correspondiente?
Un aspecto importante de la gestión de dependencias, en cualquier lenguaje, es hacer las verificaciones necesarias para asegurarte de que el paquete tenga buen mantenimiento y no presente problemas de seguridad. Una forma de conocer el estado general de un paquete es usar Snyk Advisor.

Con Snyk Advisor, puedes consultar el estado de las bibliotecas de distintos ecosistemas, como PyPI y npm. También puedes revisar imágenes base de Docker y consultar sus estadísticas generales, popularidad, etiquetas disponibles y otra información útil.
Volvamos a nuestro proyecto relacionado con PostgreSQL y asegurémonos de que el estado del paquete postgres esté dentro de un rango razonable:

Parece que el paquete postgres no obtiene una puntuación muy buena: tiene una calificación de 56 sobre 100. No es muy popular, con apenas 10 000 descargas a la semana, y su última versión se publicó hace dos años, lo que podría indicar que su mantenimiento es deficiente.
Al desplazarnos hacia abajo hasta las secciones de seguridad y comunidad de esa página, destaca el riesgo de licencia de la versión más reciente del paquete —la versión 3.0.0, del 19 de octubre de 2019—, que merece una revisión más detallada:

Si decides usar este paquete, después de seguir el paso anterior de pip install, tu sistema tendrá acceso al paquete postgres.
Para importarlo en tus proyectos:
Ahora deberías ver por qué las dependencias en Python pueden complicarse. Si le paso este script a un amigo que no tiene Python y trata de ejecutarlo, recibirá un error.
¿Por qué aparece un error?
En primer lugar, tu amigo necesita tener Python instalado. En segundo lugar, necesita los paquetes requeridos por tu proyecto, en este caso, postgres.
Además, el entorno de Python también necesita todos los módulos necesarios para ejecutar el script. Esto es similar a lo que ocurre en otros lenguajes cuando falta una biblioteca o código fuente específico.
Por lo tanto, hay dos requisitos si quiero compartir mi proyecto de Python con un amigo:
Todos los archivos necesarios para ejecutar Python
El paquete
postgres
Gestión de dependencias en Python
Si quieres compartir tus proyectos de Python con alguien, debes incluir un archivo llamado requirements.txt. Puedes usar el comando pip para instalar específicamente las dependencias que necesita el proyecto:
Usamos pip3 en lugar de solo pip para asegurarnos de no instalar la versión equivocada. pip apunta a la versión de Python que instalaste primero. Por eso, si primero instalaste una versión de Python 2, el comando pip apuntará a pip2, que se usa para instalar paquetes de Python 2.
Por lo tanto, el término pip3 le indica explícitamente a pip que instale el paquete de Python 3.
Si no tienes ninguna versión de Python 2 instalada en tu computadora, no tienes que preocuparte por esto.
Puedes comprobar qué pip (pip2 o pip3) usa tu comando pip ejecutando esto en la consola:
Este comando leerá el archivo de texto requirements.txt, que declara todas las dependencias necesarias para este proyecto, y luego instalará los paquetes que contiene.
Entonces, para que los paquetes se instalen cuando alguien ejecute este comando:
Debes crear este archivo de manifiesto de paquetes
El formato para incluir paquetes en este archivo debe ser el siguiente:
<Package name> <Higher/equal to> <some version>
Por ejemplo:
Los operadores de comparación se usan para verificar las versiones. Así se asegura que el administrador de paquetes pip instale las versiones correctas para tu proyecto. Si no se especifica ninguna versión, se instala la más reciente.
Así, si compartes el código fuente de tu proyecto con tus amigos y les indicas que ejecuten el comando pip3 con el archivo requirements.txt incluido en el proyecto, tendrán las dependencias de código abierto necesarias para ejecutarlo.
¿Qué hay de los administradores de dependencias de Python?
Además del archivo de manifiesto de paquetes que conocimos (requirements.txt), hay algunos administradores de paquetes que puedes usar para facilitar el mantenimiento y la gestión de las dependencias de proyectos en Python. Aquí tienes algunos que puedes instalar y usar:
Poetry
Poetry te permite crear archivos de bloqueo que contienen las dependencias de tu proyecto. El archivo de bloqueo se instala automáticamente cuando instalas el paquete. Una ventaja de este archivo es que Poetry facilita la actualización de las dependencias que necesita el proyecto.
Poetry funciona con herramientas de línea de comandos. Por eso, comandos como:
Estos comandos facilitan el seguimiento y la adición de dependencias a este archivo de bloqueo y, posteriormente, a tu paquete de PyPI.
También puedes usar la opción --tree para mostrar un diagrama en forma de árbol de las dependencias de tu proyecto:
Poetry facilita la gestión y la incorporación de dependencias.
pyenv
pyenv es una herramienta sencilla que te permite cambiar entre distintas versiones de Python. Así puedes comprobar si tus dependencias dejarían de funcionar con una versión anterior de Python. Como ese es su uso principal, no ofrece las funciones de otros administradores de dependencias, como Poetry.
Sin embargo, si necesitas una herramienta para comprobar si tu paquete funcionaría con una versión anterior de Python, pyenv te será útil.
Setuptools
Este también es un paquete que ayuda a gestionar paquetes. Es un poco más complejo que Poetry, por ejemplo, pero cumple su función.
Como su nombre indica, Setuptools ayuda a preparar el paquete para los usuarios; es decir, a asegurarse de que tengan los paquetes correctos para ejecutar el script.
Con setuptools, creas dos archivos: uno pyproject.toml y otro setup.py/setup.cfg.
En el archivo .toml, agrega el siguiente código para indicarle a Python que usarás Setuptools para especificar la información de tu paquete:
Ahora, en tu archivo setup.py/setup.cfg, tendrías algo como esto:
Ahora necesitarás una herramienta de compilación, como PyPA build. Tu proyecto se compilará en un archivo .gz y estará listo para distribuirse.
Setuptools requiere que hagas más trabajo manual, pero es eficiente para gestionar paquetes y asegurarse de que tus usuarios tengan todos los paquetes necesarios para ejecutar el script.
Estos tres administradores de dependencias son algunas de las opciones más populares. Cada uno tiene sus ventajas y desventajas. Sin importar cuál elijas, todos funcionan bien y permiten simplificar de manera eficiente la pesadilla de gestionar dependencias en Python.

Mejor aún, Snyk CLI te muestra la ruta de dependencias que conduce a la vulnerabilidad y cómo solucionar el problema: actualizando a una versión más reciente que incluya una corrección de seguridad.
Para terminar
Las vulnerabilidades en las bibliotecas de código abierto no son el único problema de seguridad. Por ejemplo, también puede haber código inseguro en tus aplicaciones de Python o contenedores inseguros que las incluyan, entre otras cosas. Daniel Berman escribió un artículo detallado sobre cómo empezar a usar Snyk para desarrollar en Python de forma segura, que recomiendo mucho como lectura complementaria a esta publicación.
Espero que hayas disfrutado de esta introducción a la gestión de dependencias y la seguridad en Python. Si quieres leer más sobre seguridad en Python, consulta estos recursos:
Comienza con Capture the Flag
Aprende a resolver desafíos de Capture the Flag con nuestro taller virtual 101 a pedido.
Lucian Irsigler es un programador apasionado que disfruta de las complejidades de la vida.


