miércoles, 4 de febrero de 2026

Automatizacion con Python - Cap1 - parte 3

Python // Automation Cookbook

Capítulo 1: Comencemos Nuestro Viaje de Automatización

Parte 3: Extracción de Datos y el Módulo Parse

En muchas tareas automatizadas, necesitamos tratar texto de entrada estructurado en un formato conocido y extraer la información relevante. Aprenderemos técnicas manuales y también una poderosa herramienta de terceros llamada parse.

RECETA_05

Extraer Datos de Cadenas Estructuradas

Imaginemos que necesitamos analizar registros de ventas con la siguiente estructura:

Formato del Log
[timestamp] - SALE - PRODUCT: id - PRICE: $precio

Un registro específico podría verse así:

ejemplo de log
[2018-05-05T10:58:41.504054] - SALE - PRODUCT: 1345 - PRICE: $09.99

Cómo Hacerlo

1. Importar las herramientas necesarias:

python
>>> import delorean
>>> from decimal import Decimal

2. Dividir el log en sus partes usando ' - ' como separador:

python
>>> log = '[2018-05-05T11:07:12.267897] - SALE - PRODUCT: 1345 - PRICE: $09.99'
>>> divide_it = log.split(' - ')
>>> timestamp_string, _, product_string, price_string = divide_it

3. Parsear cada elemento al tipo apropiado:

python
# Timestamp - eliminar corchetes y parsear
>>> timestamp = delorean.parse(timestamp_string.strip('[]'))

# Product ID - dividir por ':' y convertir a int
>>> product_id = int(product_string.split(':')[-1])

# Precio - dividir por '$' y convertir a Decimal
>>> price = Decimal(price_string.split('$')[-1])

4. Resultado final:

resultado
(Delorean(datetime=datetime.datetime(2018, 5, 5, 11, 7, 12, 267897), timezone='UTC'), 1345, Decimal('9.99'))

Clase PriceLog

Podemos encapsular esta lógica en una clase reutilizable:

price_log.py
class PriceLog:
    def __init__(self, timestamp, product_id, price):
        self.timestamp = timestamp
        self.product_id = product_id
        self.price = price
    
    def __repr__(self):
        return f'<PriceLog ({self.timestamp}, {self.product_id}, {self.price})>'
    
    @classmethod
    def parse(cls, text_log):
        divide_it = text_log.split(' - ')
        tmp_string, _, product_string, price_string = divide_it
        timestamp = delorean.parse(tmp_string.strip('[]'))
        product_id = int(product_string.split(':')[-1])
        price = Decimal(price_string.split('$')[-1])
        return cls(timestamp=timestamp, product_id=product_id, price=price)
¡Nunca uses float para precios! Los números float tienen problemas de precisión. Por ejemplo: 0.1 + 0.1 + 0.1 = 0.30000000000000004. Usa siempre Decimal o centavos como enteros.
RECETA_06

Usar una Herramienta de Terceros: Parse

Aunque el análisis manual funciona bien para cadenas simples, puede ser laborioso ajustar la fórmula para variaciones de entrada. El módulo parse nos permite invertir cadenas de formato de forma elegante.

Preparación

Agregar parse al archivo requirements.txt:

requirements.txt
delorean==1.0.0
requests==2.22.0
parse==1.14.0
terminal
$ pip install -r requirements.txt

Cómo Hacerlo

1. Importar y definir el log:

python
>>> from parse import parse
>>> LOG = '[2018-05-06T12:58:00.714611] - SALE - PRODUCT: 1345 - PRICE: $09.99'

2. Definir el formato como lo harías al imprimir:

python
>>> FORMAT = '[{date}] - SALE - PRODUCT: {product} - PRICE: ${price}'

3. Ejecutar parse (resultado como strings):

python
>>> result = parse(FORMAT, LOG)
>>> result['date']
'2018-05-06T12:58:00.714611'
>>> result['product']
'1345'
>>> result['price']
'09.99'

Definir Tipos

Podemos especificar tipos para conversión automática:

python
>>> FORMAT = '[{date:ti}] - SALE - PRODUCT: {product:d} - PRICE: ${price:05.2f}'
>>> result = parse(FORMAT, LOG)
>>> result['date']
datetime.datetime(2018, 5, 6, 12, 58, 0, 714611)
>>> result['product']
1345
>>> result['price']
9.99

Tipos Personalizados

Para evitar problemas con float en precios, definimos un tipo personalizado:

python
>>> from decimal import Decimal

>>> def price(string):
...     return Decimal(string)

>>> FORMAT = '[{date:ti}] - SALE - PRODUCT: {product:d} - PRICE: ${price:price}'
>>> parse(FORMAT, LOG, {'price': price})
# result['price'] = Decimal('9.99')
El módulo parse invierte el método format: lo que normalmente usarías para crear una cadena formateada, ahora lo usas para extraer valores. El especificador :ti es para timestamps ISO.

Clase PriceLog con Parse

price_log_parse.py
import parse
from decimal import Decimal
import delorean

class PriceLog:
    @classmethod
    def parse(cls, text_log):
        def price(string):
            return Decimal(string)
        
        def isodate(string):
            return delorean.parse(string)
        
        FORMAT = ('[{timestamp:isodate}] - SALE - PRODUCT: {product:d} - '
                  'PRICE: ${price:price}')
        formats = {'price': price, 'isodate': isodate}
        result = parse.parse(FORMAT, text_log, formats)
        return cls(timestamp=result['timestamp'],
                   product_id=result['product'],
                   price=result['price'])

Basado en "Python Automation Cookbook" // Jaime Buelta

Traducción al español // Capítulo 1, Parte 3 de 5