Scripts y automatización de archivos

Combinar varios CSV y conservar el nombre de cada archivo de origen

Combina en orden archivos CSV con la misma estructura de columnas y añade la columna source_file. Comprueba con datos pequeños los nombres de artículos con comas, las columnas ausentes y las salidas ya existentes.

Ver el índice

La traducción se ha realizado con IA. Comprueba el código, las unidades y los valores junto con el original. La revisión por hablantes nativos de cada idioma aún no se ha completado. 한국어

Para quién esPrincipiantes en Python que quieren reunir en una sola tabla archivos CSV separados por fecha o responsable

Preparación
  • Prepara Python 3.12 o posterior y comprueba la versión con python --version en la terminal.
  • Extrae el ZIP de ejemplo en una carpeta nueva. No lo ejecutes directamente dentro del archivo comprimido.
  • Abre la terminal en la carpeta donde está example.py. Si el comando python no está disponible en Windows, usa py; en macOS y Linux, usa python3 según tu entorno.
  • No necesitas instalar paquetes externos ni tener una cuenta. Los materiales incluidos son datos sintéticos de elaboración propia.

01Combinar dos archivos en cinco filas

Si las cifras parecen incorrectas después de combinar varios archivos, puede ser difícil localizar su origen. Este ejemplo conserva las cuatro columnas existentes y añade source_file al final. El objetivo es poder identificar el archivo de origen directamente en cada fila del resultado. Antes de empezar, suma las 2 y 3 filas de datos de los dos archivos y anota el resultado esperado: 5.

  1. Busca inputs/sales_01.csv e inputs/sales_02.csv en la carpeta extraída.
  2. Abre ambos archivos en un editor de texto y comprueba que la primera línea sea date,item,quantity,unit_price.
  3. Ejecuta el siguiente comando en la terminal, desde la carpeta que contiene example.py.
  4. Abre outputs/merged.csv y comprueba las cinco filas de datos y la columna source_file.
bash
python example.py

Las carpetas de entrada y salida están separadas, de modo que un merged.csv anterior no se incorpora a los archivos de entrada al volver a ejecutar. La búsqueda de entradas también toma como referencia fija la ubicación de example.py. Si extraes el ZIP manteniendo la estructura de carpetas, no necesitas modificar las rutas.

02Unificar las columnas antes de combinar

Columna de entradaValor de ejemploTratamiento en este artículo
date2026-09-01Se conserva la cadena tal cual
item노트Se conserva, incluidas las comas y las comillas
quantity2Se conserva como cadena, sin cálculos
unit_price2500Se conserva como cadena, sin cálculos

No solo deben coincidir los nombres de columna, sino también su orden. Por ejemplo, el programa se detiene si un archivo usa qty en lugar de quantity o cambia la posición de unit_price. Como no intenta adivinar el significado ni ajustar las columnas automáticamente, puedes detectar enseguida que se han mezclado formatos de otros departamentos.

Los datos sintéticos incluyen «메모지, 대형» y «표지 "파랑"», que contiene comillas dobles. Leer un CSV separándolo simplemente por comas con split puede dividir mal estos valores. Deja que el módulo estándar csv gestione las reglas de entrecomillado y vuelve a escribir las filas tal como se han leído.

03Código completo para ejecutar

collect_rows comprueba la cabecera y las filas de cada CSV y añade el nombre del archivo de origen. main crea la nueva salida solo cuando todas las comprobaciones han pasado. Este orden evita dejar un resultado con solo los primeros archivos combinados si las columnas de un archivo posterior son incorrectas.

example.py
"""inputs의 같은 구조 CSV를 결합합니다. 각 행에 원본 파일명을 붙입니다."""

import csv
import sys
from pathlib import Path

BASE = Path(__file__).resolve().parent
INPUT = BASE / "inputs"
OUTPUT = BASE / "outputs"
FIELDS = ["date", "item", "quantity", "unit_price"]


def collect_rows():
    if INPUT.is_symlink() or not INPUT.is_dir():
        raise ValueError("inputs 폴더가 없거나 링크입니다.")
    if getattr(INPUT, "is_junction", lambda: False)():
        raise ValueError("연결 디렉터리는 처리하지 않습니다.")
    # inputs 바로 아래의 .csv 파일만 읽습니다. 순서를 명시해 결과를 재현합니다.
    paths = sorted(
        (p for p in INPUT.iterdir() if p.suffix.lower() == ".csv"),
        key=lambda p: p.name.casefold(),
    )
    if not paths:
        raise ValueError("inputs에 CSV 파일이 없습니다.")
    merged = []
    counts = []
    for path in paths:
        if path.is_symlink() or not path.is_file():
            raise ValueError(f"일반 CSV 파일이 아닙니다: {path.name}")
        with path.open("r", encoding="utf-8-sig", newline="") as stream:
            reader = csv.DictReader(stream, strict=True)
            if reader.fieldnames != FIELDS:
                raise ValueError(f"{path.name}: 열 이름과 순서는 {FIELDS}여야 합니다.")
            count = 0
            for row in reader:
                # 열이 많으면 None 키, 적으면 None 값이 생깁니다.
                if None in row or any(value is None or not value.strip() for value in row.values()):
                    raise ValueError(f"{path.name}, {reader.line_num}행: 열 수 또는 빈 값을 확인하세요.")
                merged.append({**row, "source_file": path.name})
                count += 1
            counts.append((path.name, count))
    return merged, counts


def main():
    if OUTPUT.exists() or OUTPUT.is_symlink():
        raise FileExistsError("outputs가 이미 있습니다. 기존 결과를 옮긴 뒤 실행하세요.")
    rows, counts = collect_rows()  # 모든 파일을 검증한 다음에 출력합니다.
    OUTPUT.mkdir()
    target = OUTPUT / "merged.csv"
    with target.open("x", encoding="utf-8-sig", newline="") as stream:
        writer = csv.DictWriter(stream, fieldnames=FIELDS + ["source_file"])
        writer.writeheader()
        writer.writerows(rows)
    for name, count in counts:
        print(f"{name}: {count}행")
    print(f"완료: {len(counts)}개 파일 → {len(rows)}행")
    print(target)
    return 0


if __name__ == "__main__":
    try:
        raise SystemExit(main())
    except (OSError, ValueError, csv.Error) as error:
        print(f"중지: {error}", file=sys.stderr)
        raise SystemExit(2)

La comprobación aprovecha que DictReader crea una clave None cuando sobran columnas de datos y valores None cuando faltan. También rechaza cadenas vacías o compuestas solo por espacios. Se usa una cadena vacía para newline y se indica una codificación que admite UTF-8 BOM, para tratar de forma consistente los saltos de línea y los caracteres coreanos.

04Comparar los recuentos de filas y su origen

Orden de los datos del resultadoitemquantitysource_file
1노트2sales_01.csv
23sales_01.csv
3노트1sales_02.csv
4메모지, 대형4sales_02.csv
5표지 "파랑"1sales_02.csv

La terminal muestra, en este orden, «sales_01.csv: 2행», «sales_02.csv: 3행» y «완료: 2개 파일 → 5행». La cabecera, que es la primera línea del resultado, no se cuenta como dato. Que 노트 aparezca en dos filas no es un error: se conservan filas originales distintas, sin calcular totales ni eliminar duplicados.

05Hacer cuatro comprobaciones antes de confiar en el resultado

  1. Comprueba que la suma de filas de las entradas, 5, coincida con el número de filas de datos del resultado.
  2. Comprueba que haya dos filas cuyo source_file sea sales_01.csv y tres cuyo valor sea sales_02.csv.
  3. Comprueba que el nombre del artículo con coma siga en una sola celda y que las comillas dobles no hayan desaparecido.
  4. Vuelve a abrir los dos archivos originales para comprobar que su contenido no ha cambiado y verifica que una nueva ejecución se detenga porque outputs ya existe.

En el trabajo real, comprobar el número de filas es distinto de comprobar los totales. Aunque el importe total coincida por casualidad, puede faltar una fila y haberse incluido otra dos veces. Como en esta fase aún no se hacen cálculos, resulta más claro comparar primero los recuentos por origen y el texto original.

06Practicar añadiendo un tercer archivo

Para volver a ejecutar, guarda el primer outputs con otro nombre. Añade sales_03.csv dentro de inputs, con la misma cabecera y una fila de datos. El recuento esperado pasa a ser de seis filas. Comprueba también que source_file en la nueva fila contenga sales_03.csv para entender la relación entre añadir una entrada y la columna de seguimiento.

Solo se incluyen los archivos con extensión .csv situados directamente en inputs. No se recorren subcarpetas de forma recursiva ni se combinan notas de texto o libros de Excel. Si no hay ningún CSV, el programa considera que la entrada se ha elegido mal y se detiene. Un CSV válido que solo tenga cabecera cuenta como 0 filas y no impide combinar los demás archivos.

07Revisar los errores en lugar de aceptar resultados parciales

Causa de la detenciónDónde comprobarCómo corregirlo
Nombres de columna u orden distintosPrimera línea del archivo indicadoHaz que coincida exactamente con las cuatro columnas requeridas.
Error en la cantidad de columnas o valores vacíosNombre de archivo y número de línea indicadoBusca celdas ausentes, separadores adicionales y valores vacíos.
Error de entrecomillado del CSVComillas dobles sin cerrarUsa una copia cuya estructura hayas reparado en un editor de CSV.
Error de codificaciónFormato de guardado del archivo de entradaCrea una copia exportada de nuevo en UTF-8.
outputs ya existeCarpeta de resultados anteriorMueve los resultados y vuelve a ejecutar.

El número de línea del error corresponde a las líneas físicas leídas del CSV. En un CSV complejo con saltos de línea dentro de valores entrecomillados, puede diferir del número de fila de datos de la hoja de cálculo. Usa primero el nombre de archivo del mensaje para acotar qué original debes revisar.

08Diferenciar la combinación de la validación de datos

Este script comprueba la estructura de columnas, los valores vacíos y la sintaxis CSV. No determina si quantity es un número, si date es una fecha real ni si los importes cumplen las reglas del negocio. Si necesitas hacer cálculos después de combinar, añade una etapa de validación independiente para la conversión numérica y los rangos permitidos.

Como reúne todas las filas en memoria y guarda solo después de comprobarlas, resulta adecuado para practicar con archivos de trabajo pequeños. Los CSV muy grandes requieren un diseño con salidas temporales y procesamiento por etapas. Un error de disco durante el guardado puede dejar resultados parciales; no lo consideres un éxito si falta el mensaje de finalización. Los cambios simultáneos en las entradas y los fallos de rutas de red quedan fuera del alcance de la verificación.

Registro de ejecución y verificación

2026-09-19 · Windows 11 · CPython 3.12.14 · Sin paquetes adicionales · Ejecutado en una copia temporal de la distribución

  • Combinados 2 CSV en 5 filas y comprobados los recuentos de source_file
  • Conservación de celdas con comas y comillas dobles
  • Rechazo de cabeceras incorrectas, columnas ausentes o adicionales, valores vacíos y entrecomillado incorrecto antes de crear la salida
  • Tratamiento de CSV con solo cabecera y de la ausencia de CSV
  • Comprobado que el SHA-256 de los originales no cambia y que se conservan las salidas existentes
Límites de la verificación
  • No se ha medido el uso de memoria con archivos grandes.
  • No se valida el significado de los números y las fechas según las reglas del negocio.
  • El sistema operativo usado para verificar la ejecución es Windows.

Criterios de redacción y verificación de todo el sitio

Archivos de ejemplo para ejecutar

Incluye código, datos de entrada e instrucciones de ejecución. Extrae el ZIP y lee primero README.txt.

Descargar ZIP de ejemplo

El código de ejemplo, los nombres de archivo y las claves de entrada se mantienen como en el original. Consulta también los comandos y los pasos de comprobación del texto traducido.

Material de práctica original · Guarda los archivos originales por separado antes de ejecutarlo.

Fuentes de referencia

Las explicaciones y los ejemplos son de elaboración propia. Puedes consultar los comportamientos y conceptos relacionados en las siguientes fuentes oficiales.