Validar una importación antes de guardar

Ciencia y tecnologíaValidar una importación antes de guardar

Importar un archivo significa aceptar muchos datos de golpe. Si guardas cada fila mientras la lees puedes descubrir un error después de haber incorporado media tabla. En esta lección diseñarás una frontera de validación: primero leer y comprobar el lote completo; después decidir si puede almacenarse. Todavía no escribiremos en una base de datos.

Un archivo legible puede contener datos incorrectos

El lector CSV resuelve separadores y comillas pero no conoce tus reglas. Una cantidad negativa puede ser texto perfectamente válido. Un código repetido puede aparecer en dos filas bien formadas. Tu aplicación debe añadir esas comprobaciones. Conviene distinguir errores del formato, errores de un campo y conflictos entre registros.

El formato exige tres columnas. Cada fila debe proporcionar exactamente esos tres valores. Si sobran campos DictReader puede agruparlos bajo la clave None. Si faltan puede asignar None a valores ausentes. Ambas situaciones deben rechazarse antes de acceder alegremente a los campos. No rellenes cantidades ausentes con cero porque estarías inventando información.

Preparar el lote sin efectos externos

Crearemos una lista temporal de artículos validados y un conjunto de códigos vistos. Esa lista todavía no representa datos guardados. Si aparece cualquier error descartaremos el intento de importación y mostraremos su causa. Como no hemos escrito en disco no hace falta deshacer cambios durante esta primera fase.

def revisar_filas(filas):
    revisadas = []
    vistos = set()
    for numero, fila in enumerate(filas, start=1):
        if None in fila or any(v is None for v in fila.values()):
            raise ValueError(f"Registro {numero}: columnas incorrectas")
        codigo = fila["codigo"].strip().upper()
        if not codigo:
            raise ValueError(f"Registro {numero}: código vacío")
        if codigo in vistos:
            raise ValueError(f"Registro {numero}: código repetido")
        vistos.add(codigo)
        revisadas.append({**fila, "codigo": codigo})
    return revisadas

Este ejemplo solo comprueba estructura, código vacío y repetición. No es todavía el importador final. Mantiene cantidad como texto y no aplica todas las reglas del nombre. Su función es mostrar el recorrido del lote. En el capítulo diecinueve sustituiremos esta práctica por un módulo completo que reutiliza el modelo del inventario.

Identificar el registro que debes corregir

El número de registro no siempre coincide con la línea física del archivo. CSV permite campos entrecomillados que ocupen varias líneas, aunque nuestro formato de nombres los rechazará. Para evitar mensajes ambiguos hablaremos de registro uno, dos y tres después de la cabecera. Si utilizas un número de línea debes explicar qué representa.

Un mensaje útil combina ubicación y motivo. «Registro 3: código repetido» permite buscar un lugar concreto. Puedes incluir el código cuando ya esté validado y no contenga caracteres de control. No vuelques archivos completos en los errores. Una explicación breve facilita corregir el dato sin llenar la pantalla de información irrelevante.

Distinguir duplicados del lote y de la base

El conjunto vistos detecta repeticiones dentro del archivo que estás leyendo. No sabe qué artículos se guardaron ayer. El conflicto con registros existentes se comprobará al insertar en la base de datos mediante una restricción de unicidad. Necesitamos ambas defensas porque responden a momentos distintos del proceso.

No elimines duplicados silenciosamente usando un diccionario. Podrías conservar el último registro y perder el primero sin avisar. Si uno dice tres unidades y otro cinco no sabes cuál es correcto. Nuestro contrato rechaza todo el lote para que la persona resuelva esa contradicción. Otra aplicación podría ofrecer un informe y una política de actualización pero tendría que definirla expresamente.

Validación completa y almacenamiento atómico

Comprobar todo antes de guardar reduce los fallos previsibles pero no garantiza que la escritura posterior termine bien. La base podría encontrar un código existente o un problema de disco. Por eso añadiremos una transacción: todas las inserciones del lote se confirman juntas o se revierten juntas. Son dos capas complementarias, no alternativas.

Para un archivo pequeño podemos cargar el lote completo en memoria. El importador final limitará el tamaño de entrada y el número de registros para mantener un alcance razonable. En procesos de millones de filas tendrías que estudiar otras estrategias. No presentes una solución de aprendizaje como si resolviera cualquier volumen sin cambios.

Decidir qué hacer con un archivo vacío

Un documento sin cabecera incumple el formato. Un documento con la cabecera correcta y ninguna fila representa un lote vacío. La aplicación final lo aceptará y comunicará cero artículos importados. Esa diferencia permite separar un formato inexistente de una tabla válida sin registros. Tus pruebas deben cubrir ambos casos.

También hay que definir el orden. Conservaremos el de lectura durante la validación pero la consulta mostrará artículos ordenados por código. No dependeremos de la posición del archivo para identificar un artículo. El código seguirá siendo la clave estable y la posición servirá únicamente para localizar un error durante la importación.

Errores habituales

Capturar un error por fila y continuar parece una forma de aprovechar datos pero cambia el contrato. Terminarías con una importación parcial que exige un informe detallado de aceptados y rechazados. Aquí hemos elegido todo o nada. No añadas un continue después de un error sin rediseñar las expectativas del usuario.

Otro fallo es limpiar el código después de comprobar duplicados. «cu001» y « CU001 » parecerían distintos hasta el momento de guardar. Normaliza primero y comprueba unicidad después. El orden de validación importa porque debes comparar la identidad que utilizará realmente el programa, no la escritura accidental del archivo recibido.

Lo que deberías recordar

  • Leer CSV no valida el significado de los campos.
  • Comprueba el lote antes de escribir.
  • Normaliza antes de detectar duplicados.
  • La transacción resolverá fallos durante el guardado.

Ejercicio práctico

Prepara tres filas como diccionarios con las claves del CSV. Una debe usar CU001 y otra « cu001 ». Ejecuta revisar_filas y comprueba que detecta la repetición tras normalizar. Anota qué registro se señala y por qué no debes conservar automáticamente uno de los dos.

Repite con una fila a la que falte un campo usando None como valor. Después utiliza tres filas correctas. Comprueba que el resultado es una lista nueva y que las entradas originales no han cambiado su código. El programa no debe crear ningún archivo durante esta práctica.

Escribe el recorrido completo que tendrá la importación final: abrir, comprobar cabecera, validar registros, detectar duplicados internos e insertar en una transacción. Añade qué capa detectará un código que ya existe en la base. Esa distinción será la comprobación principal de tu ejercicio y se utilizará en la prueba final del curso.

Siguiente: Representar artículos con un modelo de datos.

Volver al índice de Programar con Python.

Últimos posts

DEJA UNA RESPUESTA

Por favor ingrese su comentario!
Por favor ingrese su nombre aquí

 

Artículos más vistos

Horóscopo diario
Menú diario