paint-brush
3 problemas principales de Python y cómo resolverlosby@dave01
3,857
3,857

3 problemas principales de Python y cómo resolverlos

David Finson18m2023/01/21
Read on Terminal Reader

La gestión de entornos de desarrollo complejos a menudo ha planteado algunos desafíos a medida que los proyectos se ampliaban. La solución es el uso de contenedores, que es un método para empaquetar una aplicación y sus dependencias en una unidad autónoma que se puede implementar y ejecutar fácilmente en cualquier plataforma. Demostraré cómo configurar y usar un entorno de desarrollo en contenedores usando Docker y Docker Compose.
featured image - 3 problemas principales de Python y cómo resolverlos
David Finson HackerNoon profile picture

Si bien trabajar con Python ha sido, en la mayoría de los casos, una experiencia fantástica para mí, administrar entornos de desarrollo complejos a menudo ha planteado algunos desafíos a medida que los proyectos se ampliaban.

Para nombrar solo algunos ejemplos, aquí hay 3 problemas importantes con Python con los que me he encontrado:

1. Las aplicaciones que dependen de las variables de entorno pueden necesitar que estas variables se configuren antes de que la aplicación pueda ejecutarse.

2. Las aplicaciones que utilizan certificados de autenticación para la comunicación entre diferentes servicios pueden requerir la generación de estos certificados localmente antes de ejecutar la aplicación.

3. Los conflictos de versiones de dependencia pueden ocurrir entre diferentes microservicios dentro del mismo proyecto.

Las cosas pueden ponerse especialmente complicadas cuando se trabaja con varios microservicios que dependen unos de otros y, francamente, como desarrollador, no quiero estar administrando todos estos gastos generales solo para ponerme en marcha. Esto es especialmente cierto si solo me estoy incorporando a un nuevo proyecto.

Una solución común que he visto usar al desarrollar aplicaciones de Python es usar entornos virtuales de Python, que son entornos aislados que contienen una instalación de Python y los paquetes necesarios. Sin embargo, la gestión de varios entornos virtuales y otras configuraciones relacionadas con el entorno aún puede llevar mucho tiempo y ser engorrosa, ya que el entorno virtual solo proporciona aislamiento en el nivel del intérprete de Python. Esto significa que otra configuración relacionada con el entorno, como las variables de entorno y la asignación de puertos, todavía se comparte globalmente para todos los componentes del proyecto.

La solución que demostraré en este artículo es el uso de contenedores, que es un método para empaquetar una aplicación y sus dependencias en una unidad autónoma que se puede implementar y ejecutar fácilmente en cualquier plataforma. Docker es una plataforma popular para desarrollar, implementar y ejecutar aplicaciones en contenedores, y Docker Compose es una herramienta que facilita la definición y ejecución de aplicaciones Docker de múltiples contenedores utilizando un solo archivo YAML (que generalmente se denomina

 docker-compose.yml
). Si bien existen soluciones alternativas como minikube , en aras de la simplicidad, me limitaré a usar Docker y Docker Compose en este ejemplo.

Demostraré cómo configurar y usar un entorno de desarrollo en contenedores con Docker y Docker Compose. También analizaré algunos de los desafíos de usar un entorno de desarrollo en contenedores y cómo superarlos configurando Docker y Docker compose para que se ajusten a los siguientes requisitos clave para un entorno de desarrollo eficaz:

1. Ejecutar: ejecución de escenarios de extremo a extremo que simulan la ejecución en el entorno de producción de destino.

2. Implementación: realizar cambios en el código y volver a implementar rápidamente, como con una pila de tiempo de ejecución de aplicaciones no en contenedores.

3. Depurar: establecer puntos de interrupción y usar un depurador para recorrer el código, como con una pila de tiempo de ejecución de aplicaciones no contenedorizadas, para identificar y corregir errores.

configuración del proyecto

Para ilustrar esto con un ejemplo, definiré una aplicación de Python simple que usa el marco web ligero de Python, Flask , para crear una API RESTful para consultar información sobre los autores y sus publicaciones. La API tiene un único punto final,

 /authors/{author_id}
, que se puede usar para recuperar información sobre un autor en particular especificando su ID como parámetro de ruta. Luego, la aplicación usa el módulo de solicitudes para realizar solicitudes HTTP a un servicio de publicaciones separado, que se espera que proporcione una lista de publicaciones de ese autor. Para mantener el código conciso, todos los datos se generarán aleatoriamente sobre la marcha utilizando la biblioteca Faker .

Para comenzar, inicializaré y luego abriré un directorio vacío para el proyecto. A continuación, crearé dos subdirectorios: el primero se llamará

 authors_service
, y el segundo
 posts_service
. Dentro de cada uno de estos directorios, crearé 3 archivos:

1.

 app.py
: el punto de entrada principal para la aplicación Flask, que define la aplicación, configura rutas y especifica las funciones que se llamarán cuando se realice una solicitud a esas rutas.

2.

 requirements.txt
: un archivo de texto sin formato que especifica los paquetes de Python necesarios para que se ejecute la aplicación.

3.

 Dockerfile
: un archivo de texto que contiene instrucciones para crear una imagen de Docker que, como se mencionó anteriormente, es un paquete liviano, independiente y ejecutable que incluye todo lo necesario para ejecutar la aplicación, incluido el código, un tiempo de ejecución, bibliotecas, variables de entorno, y casi cualquier otra cosa.

En cada

 app.py
archivo, implementaré un microservicio Flask con la lógica deseada.

para

 authors_service
, la
 app.py
archivo se ve de la siguiente manera:

 import os import flask import requests from faker import Faker app = flask.Flask(__name__) @app.route( "/authors/<string:author_id>" , methods=[ "GET" ] )
def get_author_by_id ( author_id: str ):
 author = {        "id" : author_id,        "name" : Faker().name(),        "email" : Faker().email(),        "posts" : _get_authors_posts(author_id) }    return flask.jsonify(author) def _get_authors_posts ( author_id: str ):
 response = requests.get(        f' {os.environ[ "POSTS_SERVICE_URL" ]} / {author_id} '
 )    return response.json() if __name__ == "__main__" : app.run( host=os.environ[ 'SERVICE_HOST' ], port= int (os.environ[ 'SERVICE_PORT' ]) )


Este código configura una aplicación Flask y define una ruta para manejar las solicitudes GET al punto final

 /authors/{author_id}
. Cuando se accede a este punto final, genera datos simulados para un autor con la identificación proporcionada y recupera una lista de publicaciones para ese autor del servicio de publicaciones separadas. Luego ejecuta la aplicación Flask, escuchando el nombre de host y el puerto especificado en las variables de entorno correspondientes.

Tenga en cuenta que la lógica anterior depende de la
 flask
,
 requests
y
 Faker
paquetes Para dar cuenta de esto, los agregaré al servicio de autores
 requirements.txt
archivo, de la siguiente manera:

 flask == 2 . 2 . 2
requests == 2 . 28 . 1
Faker == 15 . 3 . 4

Tenga en cuenta que no existen requisitos de versiones de paquetes específicos para ninguna de las dependencias a las que se hace referencia en esta guía. Las versiones utilizadas fueron las últimas disponibles en el momento de redactar este documento.

Para el

 posts_service
,
 app.py
se ve de la siguiente manera:

 import os import uuid from random import randint import flask from faker import Faker app = flask.Flask(__name__) @app.route( '/posts/<string:author_id>' , methods=[ 'GET' ] )
def get_posts_by_author_id ( author_id: str ):
 posts = [ {            "id:" : str (uuid.uuid4()),            "author_id" : author_id,            "title" : Faker().sentence(),            "body" : Faker().paragraph() }        for _ in range (randint( 1 , 5 )) ]    return flask.jsonify(posts) if __name__ == '__main__' : app.run( host=os.environ[ 'SERVICE_HOST' ], port= int (os.environ[ 'SERVICE_PORT' ]) )


En este código, cuando un cliente (es decir,

 authors_service
) envía una solicitud GET a la ruta
 /posts/{author_id}
, la función
 get_posts_by_author_id
se llama con el especificado
 author_id
como parámetro. La función genera datos simulados para entre 1 y 5 publicaciones escritas por el autor utilizando la biblioteca Faker y devuelve la lista de publicaciones como una respuesta JSON al cliente.

También tendré que agregar los paquetes del matraz y Faker al servicio de publicaciones.

 requirements.txt
archivo, de la siguiente manera:

 flask == 2 . 2 . 2
Faker == 15 . 3 . 4

Antes de contener estos servicios, consideremos un ejemplo de por qué querría empaquetarlos y ejecutarlos de forma aislada entre sí en primer lugar.

Ambos servicios utilizan las variables de entorno.

 SERVICE_HOST
y
 SERVICE_PORT
para definir el socket en el que se iniciará el servidor Flask. Tiempo
 SERVICE_HOST
no es un problema (múltiples servicios pueden escuchar en el mismo host),
 SERVICE_PORT
puede causar problemas. Si tuviera que instalar todas las dependencias en un entorno local de Python y ejecutar ambos servicios, el primer servicio que se iniciaría usaría el puerto especificado, lo que provocaría que el segundo servicio fallara porque no podía usar el mismo puerto. Una solución simple es usar variables de entorno separadas (p. ej.,
 AUTHORS_SERVICE_PORT
y
 POSTS_SERVICE_PORT
) en cambio. Sin embargo, modificar el código fuente para adaptarlo a las restricciones ambientales puede volverse complejo cuando se amplía.

La creación de contenedores ayuda a evitar problemas como este al configurar el entorno para que se adapte a la aplicación, y no al revés . En este caso, puedo configurar el

 SERVICE_PORT
variable de entorno a un valor diferente para cada servicio, y cada servicio podrá usar su propio puerto sin interferencia de otros servicios.

Para contenerizar los servicios, crearé un nuevo archivo llamado
 Dockerfile
en el directorio de cada servicio. El contenido de este archivo (para ambos servicios) es el siguiente:

 FROM python: 3.8
RUN mkdir /app WORKDIR /app COPY requi rements.txt /app/
RUN pip install -r requi rements.txt
COPY . /app/ CMD [ "python" , "app.py" ]

Esto

 Dockerfile
se basa en una imagen principal de Python 3.8 y configura un directorio para la aplicación en el contenedor. Luego copia el
 requirements.txt
archivo de la máquina host al contenedor e instala las dependencias enumeradas en ese archivo. Finalmente, copia el resto del código de la aplicación de la máquina host al contenedor y ejecuta el script principal de la aplicación cuando se inicia el contenedor.

A continuación, crearé un archivo llamado

 docker-compose.yml
en el directorio raíz del proyecto. Como se mencionó brevemente anteriormente, este archivo se usa para definir y ejecutar aplicaciones Docker de varios contenedores. En el
 docker-compose.yml
archivo, puedo definir los servicios que componen la aplicación, especificar las dependencias entre ellos y configurar cómo deben construirse y ejecutarse. En este caso, queda de la siguiente manera:

 ---
# Specify the version of the Docker Compose file format
version: '3.9'
services:
  # Define the authors_service service
  authors_service:
    # This service relies on, and is therefor dependent on, the below `posts_service` service
    depends_on:
      - posts_service
    # Specify the path to the Dockerfile for this service
    build:
      context: ./authors_service
      dockerfile: Dockerfile
    # Define environment variables for this service
    environment:
      - SERVICE_HOST=0.0.0.0
      - PYTHONPATH=/app
      - SERVICE_PORT=5000
      - POSTS_SERVICE_URL=http://posts_service:6000/posts
    # Map port 5000 on the host machine to port 5000 on the container
    ports:
      - "5000:5000"
    # Mount the authors_service source code directory on the host to the working directory on the container
    volumes:
      - ./authors_service:/app
  # Define the posts_service service
  posts_service:
    # Specify the path to the Dockerfile for this service
    build:
      context: ./posts_service
      dockerfile: Dockerfile
    # Define environment variables for this service
    environment:
      - PYTHONPATH=/app
      - SERVICE_HOST=0.0.0.0
      - SERVICE_PORT=6000
    # Mount the posts_service source code directory on the host to the working directory on the container
    volumes:
      - ./posts_service:/app


Ejecutando la aplicación

Los contenedores se pueden iniciar con el

 docker-compose up
dominio. La primera vez que se ejecuta, las imágenes de la ventana acoplable se generarán automáticamente.

Esto satisface el primer requisito básico anterior de "Ejecutar".

Reimplementación

Tenga en cuenta que en el

 docker-compose.yml
archivo, los montajes de volumen se utilizan para compartir los directorios de código fuente para el
 authors_service
y
 posts_service
servicios entre la máquina host y los contenedores. Esto permite que el código se edite en la máquina host y los cambios se reflejen automáticamente en los contenedores (y viceversa).

Por ejemplo, la siguiente línea monta el

 ./authors_service
directorio en la máquina host al
 /app
directorio en el
 authors_service
envase:

 volumes: - . /authors_service:/ app

Los cambios realizados en la máquina host están disponibles de inmediato en el contenedor, y los cambios realizados en el contenedor se conservan inmediatamente en el directorio de código fuente de la máquina host. Esto permite volver a implementar rápidamente los cambios al reiniciar el contenedor relevante sin reconstruir la imagen, satisfaciendo efectivamente el segundo requisito central de "Implementar".

depuración

Aquí es donde se involucra un poco más. Los depuradores en Python usan las herramientas de depuración proporcionadas por el intérprete para pausar la ejecución de un programa e inspeccionar su estado en ciertos puntos. Esto incluye establecer una función de seguimiento con

 sys.settrace()
en cada línea de código y comprobando los puntos de interrupción, además de utilizar funciones como la pila de llamadas y la inspección de variables. La depuración de un intérprete de Python que se ejecuta dentro de un contenedor puede potencialmente agregar complejidad en comparación con la depuración de un intérprete de Python que se ejecuta en una máquina host. Esto se debe a que el entorno del contenedor está aislado de la máquina host.

Para superar esto, se puede tomar una de las siguientes dos vías generales: el código se puede depurar desde dentro del propio contenedor o se puede depurar mediante un servidor de depuración remoto.

Primero, usaré VSCode como el editor de elección para demostrar cómo hacer esto. Luego, explicaré cómo trabajar de manera similar con JetBrains PyCharm .

Depuración del código desde el propio contenedor

Para desarrollar y depurar código desde un contenedor docker en ejecución usando VSCode, haré lo siguiente:

1. Asegúrese de que la extensión Docker para VSCode esté instalada y habilitada.

2. Asegúrese de que el contenedor al que quiero adjuntar esté en funcionamiento.

3. Abra la vista del explorador de la extensión Docker haciendo clic en el icono de Docker en la barra lateral izquierda.

4. En la vista del explorador, expanda la sección "Contenedores en ejecución" y seleccione el contenedor al que quiero adjuntar.

5. Haga clic con el botón derecho en el contenedor y seleccione la opción "Adjuntar código de Visual Studio" en el menú contextual.

Esto adjuntará Visual Studio Code al contenedor seleccionado y abrirá una nueva ventana de VSCode dentro del contenedor. En esta nueva ventana, puedo escribir, ejecutar y depurar código como lo haría normalmente en un entorno local.

Para evitar tener que instalar extensiones de VSCode como Python cada vez que se reinicia el contenedor, puedo montar un volumen dentro del contenedor que almacena las extensiones de VSCode. De esta forma, cuando se reinicie el contenedor, las extensiones seguirán estando disponibles porque están almacenadas en la máquina host. Para hacer esto usando docker compose en este proyecto de demostración, el

 docker-compose.yml
El archivo se puede modificar de la siguiente manera:

 ---
# Specify the version of the Docker Compose file format
version: '3.9'
services:
  # Define the authors_service service
  authors_service:
    ...
    # Mount the authors_service source code directory on the host to the working directory on the container
    volumes:
      - ./authors_service:/app
      # Mount the vscode extension directory on the host to the vscode extension directory on the container
      - /path/to/host/extensions:/root/.vscode/extensions
  # Define the posts_service service
  posts_service:
    ...

Tenga en cuenta que las extensiones de VSCode normalmente se pueden encontrar en

 ~/.vscode/extensions
en Linux y macOS, o
 %USERPROFILE%\.vscode\extensions
en Windows

Uso de un servidor de depuración de Python remoto

El método de depuración anterior funciona bien para scripts independientes o para escribir, ejecutar y depurar pruebas. Sin embargo, la depuración de un flujo lógico que involucra varios servicios que se ejecutan en diferentes contenedores es más compleja.

Cuando se inicia un contenedor, el servicio que contiene normalmente se inicia inmediatamente. En este caso, los servidores Flask en ambos servicios ya se están ejecutando en el momento en que se adjunta VSCode, por lo que hacer clic en "Ejecutar y depurar" e iniciar otra instancia del servidor Flask no es práctico, ya que daría lugar a que se ejecuten varias instancias del mismo servicio. en el mismo contenedor y compitiendo entre sí, lo que generalmente no es un flujo de depuración confiable.

Esto me lleva a la opción número dos; utilizando un servidor de depuración de Python remoto. Un servidor de depuración de Python remoto es un intérprete de Python que se ejecuta en un host remoto y está configurado para aceptar conexiones de un depurador. Esto permite el uso de un depurador que se ejecuta localmente para examinar y controlar un proceso de Python que se ejecuta en un entorno remoto.

Es importante tener en cuenta que el término "remoto" no se refiere necesariamente a una máquina físicamente remota o incluso a un entorno local pero aislado, como un contenedor Docker que se ejecuta en una máquina host. Un servidor de depuración remoto de Python también puede ser útil para depurar un proceso de Python que se ejecuta en el mismo entorno que el depurador. En este contexto, usaré un servidor de depuración remoto que se ejecuta dentro del mismo contenedor que el proceso que estoy depurando. La diferencia clave entre este método y la primera opción de depuración que cubrimos es que me adjuntaré a un proceso preexistente en lugar de crear uno nuevo cada vez que quiera ejecutar y depurar el código.

Para comenzar, el primer paso es agregar el paquete debugpy al

 requirements.txt
archivos para ambos servicios. debugpy es un depurador de Python de código abierto y alto nivel que se puede usar para depurar programas de Python de forma local o remota. Agregaré la siguiente línea a ambos
 requirements.txt
archivos:

 debugpy == 1 . 6 . 4

Ahora necesito reconstruir las imágenes para instalar debugpy en las imágenes de Docker para cada servicio. ejecutaré el

 docker-compose build
comando para hacer esto. Entonces correré
 docker-compose up
para lanzar los contenedores.

A continuación, adjuntaré VSCode al contenedor en ejecución que contiene el proceso que quiero depurar, como hice anteriormente.

Para adjuntar un depurador a la aplicación Python en ejecución, tendré que agregar el siguiente fragmento al código en el punto desde el que deseo comenzar la depuración:

 import debugpy; debugpy.listen( 5678 )

Este fragmento importa el módulo de depuración y llama al

 listen
función, que inicia un servidor de depuración que escucha las conexiones de un depurador en el número de puerto especificado (en este caso, 5678).

Si quisiera depurar el

 authors_service
, podría colocar el fragmento anterior justo antes del
 get_author_by_id
declaración de función dentro del
 app.py
archivo - de la siguiente manera:

 import os import flask import requests from faker import Faker app = flask.Flask(__name__) import debugpy; debugpy.listen( 5678 ) @app.route( "/authors/<string:author_id>" , methods=[ "GET" ] )
def get_author_by_id ( author_id: str ):
...

Esto iniciaría un servidor de depuración en el inicio de la aplicación como el

 app.py
se ejecuta el script.

El siguiente paso es crear una configuración de lanzamiento de VSCode para depurar la aplicación. En el directorio raíz del servicio cuyo contenedor he adjuntado (y en el que estoy ejecutando la ventana de VSCode), crearé una carpeta denominada

 .vscode
. Luego, dentro de esta carpeta, crearé un archivo llamado
 launch.json
, con los siguientes contenidos:

 {    "version" : "0.2.0" ,    "configurations" : [ {            "name" : "Python: Remote Attach" ,            "type" : "python" ,            "request" : "attach" ,            "connect" : {                "host" : "localhost" ,                "port" : 5678
 } } ] }

Esta configuración especifica que VSCode debe adjuntarse a un depurador de Python que se ejecuta en la máquina local (es decir, el contenedor actual) en el puerto 5678, que, lo que es más importante, fue el puerto especificado al llamar al

 debugpy.listen
función de arriba.

Luego guardaré todos los cambios. En la vista del explorador de la extensión Docker, haré clic con el botón derecho en el contenedor al que estoy conectado actualmente y seleccionaré "Reiniciar contenedor" en el menú contextual (hecho en la instancia local de VSCode). Después de reiniciar el contenedor, la ventana de VSCode dentro del contenedor mostrará un cuadro de diálogo que me preguntará si quiero volver a cargar la ventana; la respuesta correcta es sí.

¡Ahora todo lo que queda es verlo en acción!Para comenzar la depuración, dentro de la instancia de VSCode que se ejecuta en el contenedor, abriré el script que quiero depurar y presionaré F5 para iniciar el depurador. El depurador se adjuntará al script y detendrá la ejecución en la línea donde

 debugpy.listen
se llama la función. Los controles del depurador en la pestaña Depurar ahora se pueden usar para recorrer el código, establecer puntos de interrupción e inspeccionar variables.

Esto satisface el requisito de "Depuración" anterior.

Desarrollo remoto y depuración con Jetbrains Pycharm IDE

Según los documentos oficiales , hay dos formas de hacer esto cuando se usa PyCharm: se puede recuperar un intérprete de una imagen de Docker usando la función de intérprete remoto y/o una configuración de servidor de depuración remota . Tenga en cuenta que estas dos opciones no son mutuamente excluyentes. Personalmente, normalmente confío principalmente en la función de intérprete remoto para el desarrollo y uso una configuración de servidor de depuración remota cuando sea necesario.



Configuración de un intérprete remoto

Para configurar un intérprete remoto en PyCharm, haré lo siguiente:

1. Haga clic en el menú emergente de la pestaña de intérpretes en la esquina inferior derecha de la ventana del IDE.

2. Haga clic en Agregar nuevo intérprete y, a continuación, seleccione Al redactar ventana acoplable... en el menú emergente.

3. En la siguiente ventana emergente, seleccione el archivo de composición de docker relevante y luego seleccione el servicio relevante del menú desplegable. PyCharm ahora intentará conectarse a la imagen de la ventana acoplable y recuperar los intérpretes de Python disponibles.

4. En la siguiente ventana, seleccione el intérprete de python que deseo usar (p. ej.

 /usr/local/bin/python
). Una vez seleccionado el intérprete, haga clic en "Crear".

PyCharm luego indexará el nuevo intérprete, después de lo cual puedo ejecutar o depurar el código como de costumbre; PyCharm orquestará la composición de Docker detrás de escena para mí siempre que lo desee.

Establecer una configuración de servidor de depuración remota

Para establecer una configuración de servidor de depuración remota, primero debo agregar dos dependencias a la correspondiente

 requirements.txt
archivo(s): pydevd y pydevd_pycharm . Estos son similares en función al paquete de depuración mostrado anteriormente, pero, como sugiere su nombre, pydevd_pycharm está diseñado específicamente para la depuración con PyCharm. En el contexto de este proyecto de demostración, agregaré las siguientes dos líneas a ambos
 requirements.txt
archivos:

 pydevd ~= 2 . 9 . 1
pydevd -pycharm== 223 . 8214 . 17

Una vez hecho esto y reconstruidas las imágenes de la ventana acoplable, puedo incrustar el siguiente fragmento de código en el código para iniciar un servidor de depuración pydevd_pycharm en el punto del código desde el que deseo comenzar la depuración:

 import pydevd_pycharm; pydevd_pycharm.settrace( 'host.docker.internal' , 5678 )

Tenga en cuenta que, a diferencia de debugpy, aquí especifiqué una dirección de nombre de host con el valor "host.docker.internal", que es un nombre DNS que se resuelve en la dirección IP interna de la máquina host desde un contenedor Docker. Esto se debe a que no estoy ejecutando PyCharm en el contenedor; en cambio, estoy configurando efectivamente el servidor de depuración para escuchar en el puerto 5678 de la máquina host .

Esta opción también existe con la depuración, pero dado que en ese caso estaba ejecutando una instancia de VSCode en el contenedor mismo, simplificó las cosas para dejar que la dirección del nombre de host sea predeterminada como "localhost" (es decir, la interfaz de bucle invertido del contenedor en sí, no el máquina anfitriona).

El paso final es establecer una configuración de ejecución que PyCharm pueda usar para conectarse al servidor de depuración remoto.

Para hacer esto, voy a:

1. Abra el cuadro de diálogo Configuración de ejecución/depuración seleccionando Ejecutar > Editar configuraciones en el menú principal.

2. Haga clic en el botón + en la esquina superior izquierda del cuadro de diálogo y seleccione Depuración remota de Python en el menú desplegable.

3. En el campo Nombre , ingrese un nombre para la configuración de ejecución.

4. En el campo Ruta del script , especifique la ruta del script que quiero depurar.

5. En el campo Host , ingrese la dirección IP de la máquina host donde se ejecutará el servidor del depurador. En este ejemplo, es "localhost".

6. En el campo Puerto , ingrese el número de puerto en el que escuchará el servidor del depurador. En este ejemplo, es 5678.

7. En la sección Asignaciones de ruta , puedo especificar cómo las rutas en la máquina host se asignan a las rutas dentro del contenedor. Esto es útil si estoy depurando código que está montado en el contenedor desde el host, ya que es posible que las rutas no sean las mismas en ambos entornos. En este ejemplo, querré mapear

 path/to/project/on/host/authors_service
en la máquina host, para
 /app
en el contenedor para la depuración de author_service, o
 path/to/project/on/host/posts_service
a
 /app
en el contenedor para depurar posts_service (estas tendrían que ser dos configuraciones de ejecución separadas).

8. Haga clic en Aceptar para guardar la configuración de ejecución.

Para comenzar la depuración, seleccionaré la configuración de ejecución anterior del menú desplegable Ejecutar y haré clic en el botón Depurar , y luego activaré los contenedores relevantes con el

 docker-compose up
dominio. El depurador de PyCharm se adjuntará al script y detendrá la ejecución en la línea donde
 pydevd_pycharm.settrace
se llama a la función, lo que me permite comenzar a eliminar esos errores.


En resumen

En esta guía, brindé una descripción general, pero práctica, de qué son los entornos de desarrollo de Python en contenedores, por qué son útiles y cómo escribir, implementar y depurar el código de Python con ellos. Tenga en cuenta que esta no es de ninguna manera una guía completa para trabajar con estos entornos. Es simplemente un punto de partida desde el cual expandirse. Aquí hay algunos enlaces útiles para ese fin:

1. Descripción general de la contenedorización por redhat

3. Documentos oficiales de Docker

4. Documentos oficiales de PyCharm de JetBrains para la depuración remota

5. Documentos oficiales de VSCode para desarrollar Python en contenedores de desarrollo

Espero que esta guía le haya resultado útil. ¡Gracias por leer!