Precauciones previas y tips
Antes de intentar el despliegue de aplicaciones Python en contenedores es conveniente verificar algunos pasos previos, con el fin de minimizar errores posteriores.
Agrupar importaciones
Si en el proyecto hay archivos o directorios de módulos, configuraciones, traducciones, etc. es conveniente que estos archivos estén agrupados en subdirectorios de la carpeta del proyecto, con el fin de ser copiados fácilmente adentro del contenedor en las rutas correctas.
Comandos ejecutables
Hay que atención al comando utilizado para la ejecución de la rutina y también a sus argumentos posicionales y opciones de entrada. De esta manera el comando podrá ser adaptado al archivo Dockerfile.
En este sentido, tener en cuenta que el alias py
para el intérprete de Python normalmente no está disponible en el contenedor.
Versiones de dependencias
Si el programa requiere paquetes adicionales entonces es importante fijar las versiones usadas indicando sus etiquetas de versión. Esto prevendrá que el código se "rompa" si los paquetes usados son actualizados descontroladamente.
Por ejemplo, si se usa
PIP para gestionar los paquetes
el comando pip freeze
sirve asegurar las versiones
de todos los paquetes en archivo TXT.
En el caso de Poetry, ese mismo control fino se puede conseguir con el archivo LOCK. Otra opción es el uso del archivo TOML que define el versionado de una manera normalmente más laxa.
Versiones de Python
No todas las versiones de Python son capaces de correr las rutinas debidos a los cambios de sintaxis, prestaciones nuevas y prestaciones obsoletas, etc. Por este motivo debe elegirse como base una imagen de Python cuya versión instalada del intérprete pueda ejecutar el código fuente correctamente.
Compatibilidad con la imagen
Las dependencias usadas deben ser capaces de ser usadas en el sistema operativo de la imagen.
Por ejemplo: el paquete psycopg2
,
que es necesario para interactuar con bases de datos PostgreSQL,
sólo funciona el Windows.
Su equivalente para sistemas GNU/Linux
es el paquete psycopg2-binary
y es ésta la versión que funcionará
en las imágenes de Python más habituales.
print vs logging
En los contenedores la salida de texto por consola
a menudo no está implementada,
por este motivo escribir texto
mediante la función print()
es problemático.
La alternativa es la lectura de texto desde la ventana de logs,
la cual es de uso estándar en los contenedores.
Para ello es necesario el uso de las funciones de logging,
las cuales requieren importación y configuración para su uso:
import logging
# uso de la consola de logs
logging.basicConfig(
level=logging.INFO, # mínimo nivel de log a publicar
format="%(asctime)s - %(levelname)s - %(message)s", #info incorporada
)
Los logs se pueden guardar en archivo
al tiempo que se muestran en consola.
La configuración se realiza fácilmente
con ayuda de las funciones
StreamHandler()
yFileHandler()
del módulo logging
tal como se muestra a continuación:
import logging
logging.basicConfig(
level=logging.INFO, # mínimo nivel de log a publicar
format="%(asctime)s - %(levelname)s - %(message)s", #info incorporada
handlers=[
# salida por consola
logging.StreamHandler(),
# salida por archivo
logging.FileHandler(
filename=ruta_archivo,
mode="a", # agregado ('append')
encoding="utf-8",
delay=True,
),
],
)
Hay varias funciones para crear los mensajes de log, las cuales tienen distintos niveles de jerarquía:
logging.debug("Texto de DEBUG") # mínima jerarquía
logging.info("Texto de INFO")
logging.warning("Texto de WARNING")
logging.error("Texto de ERROR")
logging.critical("Texto de CRITICAL") # máxima jerarquía
Las llamadas a funciones de logging que no cumplan la jerarquía mínima configuradas serán ignoradas durante la ejecución.
f-strings vs lazy format
Es prudente evitar los f-strings, porque si el tipo de datos de entrada del string es erróneo se puede producir una excepción que encubrirá la información del reporte original.
Su reemplazo son los strings con lazy format.
Por ejemplo, la línea:
se convierte en:
Más información sobre el logging: módulo logging