Trabajo práctico grupal
Decoradores para monitoreo de ejecución en Python
1 Objetivo
El objetivo de este trabajo práctico es implementar un decorador en Python que permita monitorear la ejecución de funciones y luego utilizarlo en un programa que realiza operaciones de ordenamiento
Monitorear la ejecución del código es una tarea fundamental en el desarrollo de software: permite detectar cuellos de botella de rendimiento, identificar funciones costosas y generar registros útiles para el debugging o auditoría.
Incorporar herramientas de monitoreo desde etapas tempranas del desarrollo favorece la escritura de código más eficiente, mantenible y confiable.
2 Decorador monitor
El decorador a implementar se llamará monitor y deberá ser capaz de registrar información sobre cada ejecución de la función decorada. Su interfaz contará con los siguientes argumentos:
funcion: la función decorada oNone. Por defecto, seráNone. Su valor será distintoNonesolo cuando se use el decorador sin argumentos.consola(bool): indica si los mensajes se muestran por consola. Por defecto esTrue.archivo(stroNone): nombre del archivo donde se escribirán los mensajes de monitoreo. Por defecto esNone. En ese caso, no se guarda ningún archivo.formato(str): cadena de formato que determina cómo se construye el mensaje de monitoreo.
2.1 Componentes del formato
La cadena de formato puede incluir los siguientes componentes:
{tiempo}: fecha y hora de la llamada en formatoYYYY-MM-DD HH:mm:ss.mss, dondemssson tres dígitos para los milisegundos.{funcion}: nombre de la función.{modulo}: nombre del módulo donde se define la función.{duracion}: duración total de la ejecución en milisegundos.
El formato por defecto es:
formato = "({tiempo}) {funcion} demoró {duracion} milisegundos."2.2 Ejemplos de formato
formato = "({tiempo}) {funcion} demoró {duracion} milisegundos."
# (2025-10-08 11:54:12.123) fun demoró 735 milisegundos.
formato = "({tiempo}) {modulo}::{funcion} demoró {duracion} milisegundos."
# (2025-10-08 11:54:12.123) __main__::fun demoró 735 milisegundos.2.3 Ejemplos de @monitor
# Ejemplo 1: comportamiento por defecto
@monitor
def fun(x, y):
return x + y
# Ejemplo 2: uso de archivo de registros
@monitor(archivo="registros.log")
def fun(x, y, z):
return x ** y * z
# Ejemplo 3: uso de formato alternativo
formato = "({tiempo}) {modulo}::{funcion} demoró {duracion} milisegundos."
@monitor(archivo="registros.log", formato=formato)
def fun(a, b):
return list(range(a, b))3 Aplicación: monitoreo de algoritmos de ordenamiento
Para comprobar el correcto funcionamiento del decorador, se deben decorar las funciones merge_sort y bubble_sort, ambas encargadas de ordenar listas de números de menor a mayor.
3.1 Implementación de los algoritmos
def bubble_sort(arr):
n = len(arr)
for i in range(n):
for j in range(0, n - i - 1):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
return arr
def _merge_sort(arr):
if len(arr) <= 1:
return arr
mitad = len(arr) // 2
izquierda = _merge_sort(arr[:mitad])
derecha = _merge_sort(arr[mitad:])
return merge(izquierda, derecha)
def merge(izquierda, derecha):
resultado = []
i = 0
j = 0
while i < len(izquierda) and j < len(derecha):
if izquierda[i] < derecha[j]:
resultado.append(izquierda[i])
i += 1
else:
resultado.append(derecha[j])
j += 1
resultado.extend(izquierda[i:])
resultado.extend(derecha[j:])
return resultado
def merge_sort(arr):
return _merge_sort(arr)3.2 Generación de datos de prueba
Para generar secuencias de números aleatorios se utilizará la función crear_numeros:
import random
def crear_numeros(n):
return [random.random() for _ in range(n)]4 Ejecución del programa
Finalmente, se debe implementar un script llamado programa.py que se ejecute desde la terminal. Este programa generará secuencias aleatorias de diferentes tamaños, las ordenará utilizando ambos algoritmos y registrará el monitoreo correspondiente.
Ejemplo de ejecución:
python programa.py -n 100 1000 5000 10000 -s monitoreo.log -v
- Con
-nse especifica una lista de tamaños de secuencias a generar. - Con
-sse indica el nombre del archivo donde se deben guardar los mensajes de monitoreo.- Si no se especifica, no se guardan los mensajes en ningún archivo.
- Con
-vse indica que se muestren los mensajes de monitoreo en la consola.
5 Entregable
La entrega de este trabajo práctico debe consistir exclusivamente en un archivo .zip que contiene los siguientes archivos, con estos nombres y contenidos exactos:
monitor.py: contiene la implementación del decoradormonitory las funciones auxiliares necesarias para su funcionamiento.programa.py: contiene las funciones de ordenamiento (merge_sortybubble_sort) y la implementación de la interfaz de línea de comandos (CLI) que admite los argumentos-n,-sy-v.salida.log: archivo generado al ejecutar el programa con el siguiente comando:python programa.py -n 100 1000 5000 10000 -s salida.log -v
No se deben incluir archivos adicionales ni con nombres distintos a los especificados.
El nombre del archivo .zip debe seguir el formato G{n}_{Apellido1}_{Apellido2}_{Apellido3}.zip, donde:
{n}es el número de grupo asignado.{Apellido1},{Apellido2},{Apellido3}son los apellidos de los integrantes del grupo.
Por ejemplo, G1_Demicco_Gonzalez_Messi.zip.
6 Evaluación
La evaluación contempla no solo la correcta ejecución del programa, sino también la calidad del código desarrollado, considerando aspectos como la organización, claridad, robustez y el uso de estructuras de datos y algoritmos apropiados
Además, el programa será ejecutado desde la línea de comandos con otros valores de entrada para verificar su correcto funcionamiento en diferentes situaciones.
7 Ayuda
Dado que el decorador tiene que poder usarse de las siguientes dos maneras:
@monitor def f(...): ... @monitor(archivo="registros.log") def f(...): ...será necesario inspeccionar si el argumento
funciondemonitores una función o no. Para ello, puede usar:if callable(funcion): # accionConsidere el método
.formatde las cadenas de caracteres para usar elformatopasado al decorador.Puede ser útil tener presente que la decoración
@monitorno es la única forma de obtener una función a partir de otra función.Algunos enlaces útiles: