Skip to main content

Una introducción (breve) a la gestión de dependencias en Python

Escrito por
Headshot of Lucian Irsigler

Lucian Irsigler

Python dependency management

14 de septiembre de 2021

0 minutos de lectura

Python 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:

print("Hello world") #main.py

Y luego lo ejecuto así:

python pathToScript/main.py

Obtenemos este resultado:

Hello world

¿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.

Diagrama de flujo que muestra main.py, un ejecutable que lee código Python y lo ejecuta

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?

pip install postgres

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.

Página de Snyk Open Source Advisor que muestra una búsqueda de paquetes y una puntuación de salud de 90/100 para el paquete nodemon.

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:

Página de Snyk Advisor para el paquete postgres de Python, que muestra una puntuación de salud de 56/100 y gráficos de popularidad y mantenimiento.

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:

Panel de seguridad de paquetes que muestra PostgreSQL versión 3.0.0, licencia MIT, sin política de seguridad y una puntuación de estado del paquete de 56/100

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:

import postgres

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:

pip3 install -r requirements.txt

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:

pip --version

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:

requirements.txt

cloudscraper==1.2.58        # Version Matching. Must be version 1.2.58
Newspaper3k >= 0.1          # Minimum version 0.1
requests != 3.4             # Version Exclusion. Anything except version 3.4
beautifulsoup4 ~= 1.1       # Compatible release. Same as >= 1.1, == 1.*
discord.py                  # Installs latest release 

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:

  1. Poetry

  2. pyenv

  3. Setuptools

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:

poetry add <module>

poetry build <module>

poetry <publish>

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:

my-package
├── pyproject.toml
├── README.rst
├── my_package
│   └── __init__.py
└── tests
    ├── __init__.py
    └── test_my_package.py

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:

[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"

Ahora, en tu archivo setup.py/setup.cfg, tendrías algo como esto:

[metadata]
name = mypackage
version = 0.0.1

[options]
packages = mypackage
install_requires =
    requests
    importlib; python_version == "2.6"

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.

Terminal que muestra el análisis de dependencias de un proyecto de Python con Flask, que detecta una ruta vulnerable en Jinja2 y recomienda actualizarlo.

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:

  1. Herramientas de gestión de dependencias para Python

  2. Qué es package-lock.json: archivos de bloqueo para paquetes de yarn y npm

  3. Cómo mantener las dependencias de npm en tu proyecto

  4. El administrador de paquetes Poetry para Python y su integración de seguridad con herramientas de análisis de composición de software

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.

Leer más

blog feature snyk container custom base recommendations
Blog

Presentamos Evo Agentic AppSec: seguridad que sigue el ritmo del desarrollo con IA

El desarrollo impulsado por IA avanza más rápido que los flujos de trabajo de seguridad tradicionales. Agentic AppSec de Snyk usa agentes de seguridad para encontrar, corregir y verificar vulnerabilidades de forma continua, mientras las personas establecen el nivel.

feature insights context
Blog

Los ataques autónomos ya están aquí. La defensa debe estar a su altura.

Los atacantes autónomos están reduciendo el tiempo disponible para defenderse. Descubre cómo el descubrimiento, la corrección, la validación y la prevención continuos pueden ayudar a los equipos de seguridad a seguirles el ritmo.

feature insights context
Blog

¿La prevención es, en esencia, un problema ya resuelto?

La prevención en el código generado por agentes está resuelta desde el punto de vista arquitectónico, pero elegir controles que protejan la seguridad sin ralentizar el desarrollo sigue siendo el desafío.