Archivos y excepciones en Python

Aprende a crear programas de Python que trabajen con archivos y gestionen errores. Lee archivos de texto (ficheros de texto) completos o línea a línea, escribe y añade texto de forma segura con sentencias with y localiza archivos mediante rutas relativas y absolutas y pathlib. Lee y escribe datos CSV con el módulo csv, incluidas filas como diccionarios. Después, captura los errores que esperas con try y except, usa else y finally, lanza tus propias excepciones con mensajes claros y crea programas que informen de archivos ausentes y datos incorrectos en lugar de cerrarse por un error.

PrincipianteUnidad 8 de 10 del curso Curso de Introducción a la programación con Python

Lo que aprenderás

  1. Abre archivos de texto, lee su contenido de la forma adecuada para cada tarea, escribe y añade texto sin perder datos y procesa un archivo línea a línea para buscar, contar y filtrar.
    • Abre un archivo de texto y lee su contenido
      Usa open() para conectar un programa con un archivo de texto, elige la forma adecuada de leerlo y convierte el texto leído en datos que puedas usar.
    • Cierra archivos automáticamente con la sentencia with
      Usa with open(...) as f: para que los archivos se cierren en el momento adecuado, incluso cuando algo salga mal.
    • Escribe y añade texto a archivos
      Elige el modo adecuado para crear, sobrescribir o ampliar un archivo y escribe texto con write() y print() para que las líneas queden exactamente como quieres.
    • Busca, cuenta y filtra líneas de un archivo
      Procesa un archivo línea a línea para encontrar las líneas que necesitas, contarlas o sumar sus valores y escribir los resultados en un archivo nuevo.
  2. Indica a Python exactamente dónde está un archivo, comprende por qué a veces un programa no encuentra un archivo que existe y construye rutas que funcionen en Windows, macOS y Linux.
    • Usa correctamente rutas relativas y absolutas
      Escribe rutas absolutas y relativas, identifica desde qué carpeta parte una ruta relativa y evita los problemas de las barras invertidas en las rutas de Windows.
    • Construye rutas y gestiona carpetas con pathlib
      Usa objetos Path del módulo pathlib para unir, examinar y comprobar rutas, localizar archivos, crear carpetas y leer o escribir archivos pequeños en un solo paso.
  3. Usa el módulo csv de Python para leer datos de tablas en archivos CSV, convertirlos en números y escribir los resultados como CSV que puedan abrir los programas de hojas de cálculo.
    • Lee datos CSV con csv.reader
      Comprende cómo almacena una tabla un archivo CSV, léelo fila a fila con csv.reader, salta la cabecera y convierte los valores que necesitas.
    • Escribe archivos CSV con csv.writer
      Crea archivos CSV a partir de listas con csv.writer para que las comas, las comillas y los terminadores de línea se gestionen correctamente.
    • Trabaja con columnas por su nombre mediante DictReader y DictWriter
      Lee cada fila CSV como un diccionario cuyas claves proceden de la cabecera, filtra y resume filas por nombre de columna y vuelve a escribir los diccionarios como CSV.
  4. Reconoce las excepciones que lanza Python, lee una traza de excepción para encontrar la causa, captura los errores que esperas y mantén el programa en ejecución o detenlo con un mensaje claro en lugar de un cierre por error.
    • Reconoce excepciones habituales y lee una traza de excepción
      Comprende qué es una excepción, lee una traza de excepción de abajo arriba y nombra los tipos de excepción habituales y sus causas típicas.
    • Captura excepciones con try y except
      Escribe bloques try y except que capturen los errores específicos que esperas, den al usuario un mensaje útil y permitan que los errores inesperados sigan mostrándose.
    • Usa else y finally y sigue la propagación de excepciones entre funciones
      Completa una sentencia try con else y finally, predice el orden en que se ejecutan sus bloques y decide en qué función debe manejarse una excepción.
    • Gestiona de forma controlada los fallos de programas que trabajan con archivos y datos
      Combina el manejo de archivos y excepciones para que los archivos ausentes o bloqueados y los datos incorrectos produzcan mensajes claros, filas omitidas o una detención controlada, en lugar de un cierre por error.
  5. Usa raise para impedir que una función continúe con datos de entrada incorrectos, elige tipos de excepción y mensajes adecuados y propaga los errores o conviértelos en otros más claros.
    • Lanza excepciones para rechazar datos de entrada no válidos
      Usa la sentencia raise para indicar que una función recibió un valor con el que no puede trabajar y deja que el código que la llamó decida cómo responder.
    • Relanza y encadena excepciones y define excepciones personalizadas
      Propaga una excepción después de reaccionar a ella, convierte un error de bajo nivel en otro más claro y crea tus propios tipos de excepción para problemas específicos de tu programa.

Guía de estudio de Archivos y excepciones en Python

5 capítulos

1

Lee y escribe archivos de texto

Los archivos permiten a un programa conservar información entre ejecuciones y trabajar con datos recopilados en otro lugar. La lectura lleva texto a la memoria; la escritura guarda resultados para la siguiente ejecución o para otra persona. Elegirás un método de lectura, controlarás exactamente lo que se escribe y usarás la sangría para mantener los archivos abiertos solo mientras se necesitan. Después, los ejemplos línea a línea combinan operaciones con cadenas, decisiones y contadores para convertir texto sin procesar en resultados útiles.

1.1 Lectura de texto en un programa

Un archivo de texto conserva la información después de que un programa se detenga. Python usa un objeto de archivo, devuelto por open(), para trabajar con esa información. La apertura conecta con el archivo; una operación de lectura recupera su texto.

Elige qué leer

El modo predeterminado es "r", de lectura. Un nombre sin ruta se busca en el directorio de trabajo actual. Si no se encuentra allí, open() lanza FileNotFoundError.

with open("fruit.txt", encoding="utf-8") as f:
    text = f.read()

Supón que el archivo tiene tres líneas, «apple», «banana» y «cherry», todas con terminador de línea. text es 'apple\nbanana\ncherry\n'. La secuencia de escape \n representa un carácter de salto de línea. La última línea también puede terminar sin un salto de línea.

OperaciónResultadoÚtil cuando
f.read()Todo el texto restante como una cadenaNecesitas un archivo pequeño completo
f.readline()La siguiente línea como cadenaNecesitas una línea en ese momento
f.readlines()Todas las líneas restantes como listaNecesitas reutilizar las líneas
for line in f:Una línea por iteraciónPuedes procesar las líneas en orden

readline() devuelve '' al final del archivo. Una línea en blanco con terminador de línea devuelve '\n', por lo que una línea en blanco y el final del archivo son distintos.

Sigue la posición

La lectura hace avanzar la posición en el archivo. Después de que f.read() haya consumido el archivo, otra llamada devuelve ''; un bucle sobre ese mismo objeto ya no tiene nada que recorrer. Vuelve a abrir el archivo para empezar de nuevo o conserva el texto o las líneas que necesites en una variable. read() y readlines() cargan en memoria lo que queda del archivo. Recorrer directamente el archivo permite procesar un archivo grande línea a línea.

Las líneas conservan sus caracteres de salto de línea. print(line) añade su propio salto, lo que puede dejar líneas en blanco adicionales en pantalla. Usa print(line, end="") para mantener el espaciado original o elimina el terminador de línea antes de imprimir. line.rstrip("\n") elimina los saltos de línea finales; line.strip() también elimina los espacios de ambos extremos.

Convierte el texto en números

Incluso los dígitos llegan como cadenas. Este archivo contiene las puntuaciones «72», «85» y «90»:

scores = []
with open("scores.txt", encoding="utf-8") as f:
    for line in f:
        scores.append(int(line))
total = sum(scores)
print(total, round(total / len(scores), 2))

La lista es [72, 85, 90], por lo que el programa imprime 247 82.33. int() acepta espacios y saltos de línea alrededor. Una cadena vacía o una palabra como "forty" lanza ValueError.

Lee los caracteres con la codificación correcta

Una codificación relaciona los caracteres con los bytes almacenados. UTF-8 puede representar caracteres como «é» y emojis. Usa encoding="utf-8" de forma explícita para los archivos UTF-8. Python 3.15 activa el modo UTF-8 de forma predeterminada; las instalaciones anteriores pueden usar una codificación local. Una codificación incorrecta puede producir texto ilegible o UnicodeDecodeError. Indicar la codificación explícitamente no convierte en UTF-8 un archivo guardado con otra codificación.

El bloque with cierra el archivo cuando termina. Un archivo cerrado no se puede leer: otro f.read() lanza ValueError.

Puntos clave

  • open() devuelve un objeto de archivo; la lectura recupera texto desde su posición actual.
  • Elige una cadena, una lista de líneas o un bucle línea a línea según la tarea.
  • El final del archivo da ''; una línea en blanco puede dar '\n'.
  • Convierte el texto numérico con int() o float() antes de calcular.
  • Usa la codificación que corresponda al archivo y ciérralo al terminar.

1.2 Archivos que se cierran al terminar el bloque

Un archivo abierto utiliza recursos del sistema operativo. El texto que se está escribiendo también puede esperar en una memoria intermedia antes de llegar al archivo. Cerrar libera los recursos y vuelca la salida pendiente de esa memoria. Una sentencia with organiza esa liberación en un punto claro del código.

Lee dentro y usa el resultado después
with open("notes.txt", encoding="utf-8") as f:
    text = f.read()
print(len(text))

Los dos puntos inician el bloque. La línea con sangría se ejecuta mientras f está abierto. Cuando la ejecución llega al print() sin sangría, el archivo ya se ha cerrado, pero text sigue siendo una cadena normal. El nombre f aún hace referencia al objeto de archivo; ahora f.closed es True.

El mismo patrón sirve para una lista:

with open("fruit.txt", encoding="utf-8") as f:
    lines = f.readlines()
for line in lines:
    print(line.strip().upper())

El bucle usa datos ya leídos y guardados en lines. Mover f.readlines() fuera del bloque intentaría leer un archivo cerrado y lanzaría ValueError.

Libera recursos cuando la ejecución cambia de dirección

Considera una función que devuelve la primera línea:

def first_line(path):
    with open(path, encoding="utf-8") as f:
        return f.readline().rstrip("\n")

El valor de retorno se prepara dentro del bloque. Después, Python sale del bloque y cierra el archivo antes de que el código que realizó la llamada reciba ese valor. El archivo también se cierra cuando una excepción sale del bloque. Nunca se llegaría a un f.close() manual situado después de una sentencia que falla.

Los objetos de archivo admiten este comportamiento porque son gestores de contexto: objetos que organizan la preparación y la liberación de recursos en torno a un bloque with. Puedes usar ese comportamiento sin escribir tu propio gestor de contexto.

Abre juntos un archivo de entrada y otro de salida
with open("in.txt", encoding="utf-8") as src, open("out.txt", "w", encoding="utf-8") as dst:
    for line in src:
        dst.write(line.upper())

Cada línea de entrada se convierte en mayúsculas y se escribe en la salida. Ambos archivos se cierran cuando termina el bloque. Si falla la segunda apertura, el primer archivo, ya gestionado por with, se cierra cuando Python sale de la sentencia.

Liberar recursos y recuperarse de errores cumplen funciones distintas

with no captura los errores de archivo. Si open() no encuentra notes.txt, lanza FileNotFoundError antes de ejecutar el cuerpo. Si la conversión de una línea con int() falla dentro del cuerpo, el archivo se cierra y la excepción sigue propagándose hacia fuera. Se necesita una cláusula except coincidente para recuperarse o mostrar un mensaje.

La ausencia de los dos puntos al final de la línea de with provoca SyntaxError.

Puntos clave

  • with cierra un archivo abierto al salir normalmente, al retornar y al salir por una excepción.
  • Las cadenas y listas almacenadas siguen siendo utilizables después de cerrar el archivo.
  • La sangría delimita el tiempo durante el que el archivo permanece abierto.
  • Liberar recursos no captura una excepción; para recuperarse hacen falta try y except.

1.3 Creación, sustitución y adición de texto al final

La escritura empieza con una decisión sobre los datos existentes. El modo controla si Python lee, sustituye, amplía o crea un archivo. Decide antes de llamar a open(), porque la sustitución ocurre de inmediato.

Elige el modo
ModoArchivo existenteArchivo inexistente
"r"Lo abre para leerLanza FileNotFoundError
"w"Lo vacía y después lo abre para escribirLo crea
"a"Añade la salida al finalLo crea
"x"Lanza FileExistsErrorLo crea

Abrir la única copia de datos importantes con "w" destruye su contenido anterior aunque no se ejecute después ningún write(). Usa un archivo de salida separado mientras aprendes a transformar datos. "x" es útil cuando se debe impedir la sustitución de un archivo existente.

Añadir "b", como en "rb", selecciona el modo binario para bytes sin procesar. Los modos de texto trabajan con cadenas y una codificación; los modos binarios no aceptan el argumento encoding.

Decide dónde terminan las líneas
with open("todo.txt", "w", encoding="utf-8") as f:
    f.write("buy milk\n")
    f.write("call Sam\n")

El archivo tiene las dos líneas «buy milk» y «call Sam». write() añade exactamente la cadena recibida, sin ningún separador automático. Sin los saltos de línea, el archivo contendría "buy milkcall Sam" en una sola línea.

write() devuelve el número de caracteres escritos. Por ejemplo, f.write("Ana,92\n") devuelve 7. Es un conteo de caracteres, no necesariamente el número de bytes codificados en disco. Acepta una cadena; f.write(42) lanza TypeError. Convierte primero los números, por ejemplo con f.write(f"{score}\n").

Compara las funciones de ayuda para la salida

print() puede escribir en un archivo:

with open("total.txt", "w", encoding="utf-8") as f:
    print("Total:", 247, file=f)

El texto de salida es "Total: 247\n". print() convierte sus argumentos, los separa con espacios y añade un salto de línea final de forma predeterminada.

writelines() recibe una secuencia de cadenas, pero no inserta terminadores de línea. f.writelines(["a", "b"]) escribe "ab". Para obtener un elemento por línea, incluye un salto de línea en cada cadena o une las cadenas con "\n" y añade un salto de línea final.

Conserva las ejecuciones anteriores
with open("log.txt", "a", encoding="utf-8") as f:
    f.write("Program started\n")

Si al principio no existe el archivo, dos ejecuciones producen dos líneas. Con "w", cada ejecución sustituiría la entrada anterior. El modo de adición al final no añade un salto de línea ausente: si el texto existente termina a mitad de una línea, el texto nuevo empieza inmediatamente después.

Para un informe, recorre pares como [("Ana", 92), ("Ben", 78)] y escribe f"{name}: {score}\n". El formato se aplica antes de escribir, por lo que f"{82.333:.1f}" produce el texto "82.3". Después, al terminar el bloque, with cierra la salida y vuelca el texto pendiente de la memoria intermedia.

Puntos clave

  • "w" vacía un archivo existente en cuanto lo abre.
  • "a" añade al final; "x" impide sustituir un archivo existente.
  • write() recibe una cadena y no añade ningún salto de línea.
  • print(..., file=f) convierte los valores y añade un salto de línea de forma predeterminada.
  • writelines() escribe cadenas consecutivas sin añadir separadores.
  • Los modos binarios leen o escriben bytes y no aceptan un argumento de codificación.

1.4 Búsqueda y guardado de líneas útiles

Muchas tareas con archivos consisten en un bucle con una decisión dentro. Lee una línea, elimina los espacios que sobren, decide si interesa y actualiza un resultado. Mantener estos pasos separados facilita comprobar un programa.

Procesa un registro de actividad

Supón que server.log contiene estos registros, con una línea en blanco antes del último:

2026-03-01 08:14 INFO Server started
2026-03-01 08:20 ERROR Disk almost full
2026-03-01 09:02 INFO User login: maya
2026-03-01 09:15 WARNING Slow response
2026-03-01 10:40 ERROR Database timeout

2026-03-01 11:05 INFO Backup finished

Cada registro no vacío tiene una fecha, una hora, un nivel y un mensaje. Divide solo tres veces para mantener unido el mensaje:

errors = 0
with open("server.log", encoding="utf-8") as f:
    for line in f:
        line = line.strip()
        if not line:
            continue
        parts = line.split(maxsplit=3)
        if parts[2] == "ERROR":
            errors += 1
            print(parts[3])
print(errors, "errors")

Para el segundo registro, parts[2] es "ERROR" y parts[3] es "Disk almost full". Se imprime ese mensaje y el contador sube a 1. El error posterior lo sube a 2. El programa imprime ambos mensajes y después «2 errors».

Busca en la parte adecuada
ComprobaciónQué pregunta
line.startswith("From:")¿Empieza la línea con este texto?
"ERROR" in line¿Aparece este texto en alguna posición?
line.find("ERROR")¿Dónde aparece por primera vez, o es el resultado -1?
parts[2] == "ERROR"¿Es este campo concreto exactamente el nivel de error?

Buscar en cualquier posición también encontraría «INFO No ERRORS today». Comprobar el campo de nivel responde con más precisión a la pregunta sobre el registro de actividad.

Después de strip(), una línea en blanco es ""; dividirla da []. Acceder a parts[2] lanzaría entonces IndexError. continue salta esa línea antes de cualquier acceso por índice. Un registro no vacío pero incompleto también necesita una comprobación de longitud cuando puedan aparecer registros así.

Cuenta categorías o escribe un archivo filtrado

Un diccionario guarda un conteo por nivel. Para cada registro, asigna level = parts[2] y después counts[level] = counts.get(level, 0) + 1. Para el registro de actividad anterior, los conteos son {'INFO': 3, 'ERROR': 2, 'WARNING': 1}. El valor predeterminado 0 inicia una categoría la primera vez que aparece.

Para guardar los registros coincidentes, abre un destino separado en la misma sentencia with y escribe una línea cuando coincida su nivel. Conserva la line original si el espaciado importa; si escribes texto limpio, vuelve a añadir su salto de línea. Nunca abras el propio origen con "w": se vaciaría antes de empezar a leer.

Observa los caracteres invisibles

print(repr(line)) hace visibles los espacios finales y los saltos de línea, por ejemplo 'Disk full \n'. strip() elimina ambos, mientras que rstrip("\n") conserva los espacios. La lectura normal de texto convierte los terminadores de línea reconocidos de Windows, Unix y los Mac antiguos en "\n". Una última línea sin terminador sigue sin tenerlo. Un nombre de archivo recogido mediante input("File name: ").strip() permite que el mismo bucle trabaje con distintos archivos de entrada.

Puntos clave

  • Limpia, selecciona, procesa e informa en pasos separados.
  • Salta las líneas en blanco antes de acceder por índice a los campos separados.
  • Comprueba el campo adecuado cuando una búsqueda en toda la línea pueda encontrar más de lo deseado.
  • Usa un diccionario para mantener un contador por categoría.
  • Escribe la salida filtrada en otro archivo.
  • repr() revela espacios y caracteres de salto de línea ocultos en la impresión normal.
2

Localiza archivos mediante rutas

Un nombre de archivo correcto es solo una parte de su ubicación. La carpeta desde la que se inicia un programa afecta a las rutas relativas y puede ser distinta de la que contiene el archivo de programa. Seguirás rutas por un árbol de carpetas, evitarás las secuencias de escape en las cadenas de Windows y construirás ubicaciones con pathlib. Estas habilidades ayudan a explicar los errores por archivos no encontrados y permiten que un mismo proyecto localice sus datos y prepare carpetas de salida en distintos equipos.

2.1 Dónde busca Python un archivo

Una ruta describe una ubicación en un árbol de carpetas. Puede comenzar en la raíz de ese árbol o en el directorio de trabajo actual del programa. Un archivo puede existir en el equipo y aun así no encontrarse en la ubicación que solicita tu programa.

Lee una ruta desde su punto de partida
TipoEjemploPunto de partida
Absoluta, macOS o Linux/Users/maya/data/notes.txtLa raíz /
Absoluta, WindowsC:/Users/Maya/data/notes.txtLa raíz de la unidad C
Relativadata/notes.txtDirectorio de trabajo actual

Supón que una carpeta llamada project contiene una carpeta scripts y otra data. Ejecutas python scripts/report.py mientras trabajas en project. Abrir "data/notes.txt" busca dentro de project/data, aunque el archivo de programa esté en project/scripts.

Si, en cambio, inicias el mismo archivo de programa mientras trabajas dentro de project/scripts, esa ruta relativa apunta al interior de project/scripts/data. El archivo de programa no se ha movido; ha cambiado el punto de partida.

from pathlib import Path
print(Path.cwd())

Esto imprime el directorio de trabajo actual. os.getcwd() después de import os proporciona la misma información como cadena. Los editores y las herramientas de ejecución pueden elegir un directorio de trabajo, así que compruébalo cuando la ubicación no esté clara.

Muévete por las carpetas

En una ruta relativa, . significa la carpeta actual y .. su carpeta padre. Desde project/scripts, ../data/notes.txt sube a project y después baja a data. Añadir .. sin comprobar la carpeta de partida puede llevar a un programa a la ubicación equivocada.

Una ruta absoluta es útil para identificar una ubicación exacta, pero una ruta como C:/Users/Maya/Desktop/data.csv vincula el código compartido a las carpetas de una persona. Usa una ruta relativa con un punto de partida claro o construye la ruta desde la carpeta del propio archivo de programa cuando los datos deban estar allí.

Conserva intactas las barras invertidas de Windows

Windows suele mostrar barras invertidas entre carpetas. En una cadena normal de Python, una barra invertida inicia una secuencia de escape: \n se convierte en un salto de línea y \t en una tabulación. Por tanto, el literal "C:\new\table.txt" no contiene la ruta que querías.

Estas formas conservan la ruta deseada:

raw = r"C:\new\table.txt"
escaped = "C:\\new\\table.txt"
forward = "C:/new/table.txt"

Python en Windows acepta barras normales. Una cadena sin procesar impide que las barras invertidas se conviertan en secuencias de escape, pero no puede terminar en una sola barra invertida. Por ejemplo, r"C:\data\" tiene una sintaxis no válida.

Comprueba el nombre además de la carpeta

Busca diferencias de escritura y extensiones ocultas: un archivo mostrado como «notes.txt» puede llamarse realmente «notes.txt.txt». Las mayúsculas y minúsculas también importan. Linux suele distinguir Data.csv de data.csv; la configuración habitual de Windows y macOS no lo hace. Respetar las mayúsculas y minúsculas reales permite que un proyecto funcione en distintos sistemas.

Puntos clave

  • Las rutas relativas parten del directorio de trabajo actual.
  • El directorio de trabajo puede ser distinto de la carpeta del archivo de programa.
  • . permanece en la carpeta actual; .. se mueve a su carpeta padre.
  • Usa cadenas sin procesar, barras invertidas duplicadas o barras normales para las rutas de Windows.
  • Comprueba los nombres exactos, las extensiones y las mayúsculas y minúsculas cuando no se encuentre un archivo.

2.2 Construcción de rutas con pathlib

El módulo estándar pathlib da a cada ruta su propio objeto. Un Path permite unir nombres de carpetas, examinar un nombre de archivo y realizar tareas habituales con archivos sin construir manualmente cadenas con separadores.

Une y examina
from pathlib import Path
p = Path("reports") / "2026" / "sales.csv"
print(p.name)
print(p.stem)
print(p.suffix)
print(p.parent)

Los tres primeros resultados son «sales.csv», «sales» y «.csv». La carpeta padre es la ruta reports/2026, que se muestra con el separador del sistema. Aquí / une partes de una ruta; no divide números. La función anterior os.path.join() también une partes de rutas representadas como cadenas.

Un Path describe una ubicación incluso antes de que exista algo en ella. p.exists() comprueba si hay algo en esa ubicación. p.is_file() y p.is_dir() distinguen un archivo de un directorio. Una comprobación de existencia no puede garantizar una apertura posterior: el archivo puede desaparecer o el acceso puede cambiar entre ambas operaciones. Maneja los errores de apertura cuando el programa necesite recuperarse.

Lee o escribe un archivo pequeño

open() acepta un Path directamente. Para un archivo pequeño, estos métodos también gestionan la apertura y el cierre:

p = Path("greeting.txt")
p.write_text("Hello\n", encoding="utf-8")
text = p.read_text(encoding="utf-8")

text pasa a ser "Hello\n". write_text() sustituye el contenido existente, igual que abrir con "w"; no sirve para añadir al final. read_text() carga el archivo completo, así que usa un bucle sobre el archivo cuando necesites procesar uno grande línea a línea.

Parte de la carpeta del archivo de programa

Un archivo de datos suministrado junto a un archivo de programa debe localizarse a partir de este, independientemente del directorio de trabajo:

base = Path(__file__).resolve().parent
scores_path = base / "data" / "scores.txt"
with open(scores_path, encoding="utf-8") as f:
    scores = f.readlines()

__file__ identifica el archivo de programa. resolve() convierte su ruta en absoluta y parent selecciona la carpeta que lo contiene. En una consola interactiva, __file__ no está definido, por lo que este patrón se usa en un archivo de programa.

Localiza archivos y prepara carpetas de salida
for p in sorted(Path("logs").glob("*.txt")):
    text = p.read_text(encoding="utf-8")
    print(p.name, len(text.splitlines()))

glob("*.txt") selecciona las rutas coincidentes en logs. iterdir() produce las entradas de la carpeta sin ese filtro de patrón. Ordenarlas hace que el orden sea predecible. splitlines() cuenta las líneas del texto sin tratar el terminador de línea final como una línea vacía adicional.

La escritura crea un archivo, pero no las carpetas padre que falten. Prepáralas primero:

folder = Path("output") / "daily"
folder.mkdir(parents=True, exist_ok=True)
(folder / "report.txt").write_text("Ready\n", encoding="utf-8")

parents=True crea las carpetas que falten por encima de daily. exist_ok=True acepta un directorio que ya exista. No convierte un archivo normal existente en una carpeta.

Puntos clave

  • Path une partes con / y funciona directamente con open().
  • name, stem, suffix y parent permiten acceder a distintas partes de una ruta.
  • Una comprobación de existencia no garantiza que una apertura posterior tenga éxito.
  • read_text() lee todo el texto; write_text() lo sustituye.
  • Construye la ruta desde Path(__file__).resolve().parent para datos relativos al archivo de programa.
  • Usa glob() para encontrar coincidencias y mkdir() para crear las carpetas que falten.
3

Lee y escribe archivos CSV

Los datos de una tabla necesitan más estructura que un conjunto de líneas. Un nombre puede contener una coma, un campo puede contener un salto de línea y una cantidad sigue llegando como texto. Usarás el módulo CSV para conservar esos límites, convertir valores para los cálculos y escribir resultados que otro programa pueda leer. Las columnas con nombre hacen más claro el procesamiento, mientras que las comprobaciones de las cabeceras y de la estructura de las filas ayudan a detectar datos incompletos.

3.1 Lectura de filas y campos CSV

Un archivo CSV almacena una tabla como texto. Sus registros son filas y sus campos son los valores de las columnas. Las comas suelen separar los campos, pero los campos entrecomillados pueden contener comas e incluso saltos de línea. Usa el módulo csv para mantener unidos esos valores.

Deja que el lector gestione las comillas
name,quiz1,quiz2
Ana,8,9
Ben,7,6
"Lopez, Maria",10,8

La primera fila es una cabecera que contiene los nombres de las columnas. La última fila de datos tiene tres campos, no cuatro: la coma dentro del nombre entrecomillado pertenece al nombre. Una comilla doble dentro de un campo entrecomillado se escribe dos veces. Dividir cada línea con split(",") ignoraría esas reglas y separaría el nombre en partes.

import csv
with open("grades.csv", newline="", encoding="utf-8") as f:
    reader = csv.reader(f)
    header = next(reader)
    for row in reader:
        average = (int(row[1]) + int(row[2])) / 2
        print(row[0], average)

El lector devuelve listas de cadenas. next(reader) consume la cabecera una vez y deja que el bucle procese los datos. El programa imprime «Ana 8.5», «Ben 6.5» y «Lopez, Maria 9.0». En la primera fila de datos, convertir "8" y "9" permite obtener un total de 17; después, dividir entre 2 da 8,5.

Coordina el manejo del archivo y la lectura de la tabla

Abre los archivos CSV con newline="" para que el módulo csv gestione por sí mismo los terminadores de línea. Esto importa cuando un campo entrecomillado incluye un salto de línea. Un registro CSV puede abarcar varias líneas físicas del archivo, por lo que dividir línea a línea no sustituye a un lector CSV.

El comportamiento predeterminado del lector mantiene los valores como cadenas. Sin conversión, sumar row[1] + row[2] une "8" y "9" para formar "89". Si olvidas saltar la cabecera, se intenta convertir "quiz1" y se lanza ValueError.

Si el archivo puede estar vacío, next(reader, None) consume la cabecera si existe y devuelve None en caso contrario. Una línea CSV completamente en blanco se convierte en []. Salta esas filas con if not row: continue antes de acceder por índice. Una fila no vacía con pocos campos también necesita una comprobación de longitud; saltar solo las filas en blanco no protege row[2] frente a todos los registros incompletos.

Ajusta la lectura al formato del archivo
reader = csv.reader(f, delimiter=";", skipinitialspace=True)

Esto selecciona el punto y coma como separador y elimina los espacios inmediatamente posteriores. Elige el separador que use realmente el archivo; cambiarlo no convierte las comas decimales en puntos decimales. float("2,50") sigue lanzando ValueError.

Algunas exportaciones de hojas de cálculo empiezan con una marca de orden de bytes UTF-8. Leerlas con encoding="utf-8" puede dejar "\ufeff" al principio del primer campo y convertir la cabecera "name" en "\ufeffname". Para ese formato, encoding="utf-8-sig" elimina el marcador; también puede leer archivos UTF-8 sin él.

Puntos clave

  • Un registro CSV puede contener comas o saltos de línea dentro de campos entrecomillados.
  • Usa csv.reader para respetar el entrecomillado, en lugar de dividir simplemente por comas.
  • Abre los archivos CSV con newline="" y la codificación correspondiente.
  • El lector predeterminado devuelve cadenas; salta la cabecera antes de convertir valores numéricos.
  • Comprueba si las filas están vacías o incompletas antes de acceder a los campos.
  • Selecciona el delimitador correcto y gestiona la marca de orden de bytes cuando exista.

3.2 Escritura de filas de una tabla como CSV

Un escritor CSV convierte los valores en campos correctamente separados y entrecomillados. Proporciónale filas como secuencias de valores y deja que gestione los signos de separación y las comillas. Así evitas una salida que parece correcta hasta que un nombre o mensaje contiene una coma.

Escribe una cabecera y los datos
import csv
with open("summary.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.writer(f)
    writer.writerow(["name", "average"])
    writer.writerow(["Ana", 8.5])
    writer.writerow(["Lopez, Maria", 9.0])

El archivo contiene las filas name,average, Ana,8.5 y "Lopez, Maria",9.0. El escritor convierte los números en texto. Entrecomilla el nombre que contiene una coma y duplica cualquier comilla doble dentro de un campo entrecomillado. None se convierte en un campo vacío, por lo que volver a leer el archivo no recupera None automáticamente.

writerow() recibe una fila. writerows() recibe una secuencia de filas, como [["Ana", 8.5], ["Ben", 6.5]]. En cambio, pasar "Ana" directamente a writerow() le proporciona tres caracteres y produce A,n,a. Usa ["Ana"] para una fila de un campo.

Deja que CSV controle los terminadores de línea

Usa newline="" al abrir la salida. El escritor predeterminado termina los registros con "\r\n". Permitir además la conversión de saltos de línea del modo texto puede añadir un retorno de carro adicional en Windows y producir líneas en blanco no deseadas en algunos lectores. El argumento newline evita esa segunda capa de conversión.

Transforma un archivo en otro
with open("grades.csv", newline="", encoding="utf-8") as src, open("summary.csv", "w", newline="", encoding="utf-8") as dst:
    reader = csv.reader(src)
    writer = csv.writer(dst)
    next(reader)
    writer.writerow(["name", "average"])
    for row in reader:
        average = (int(row[1]) + int(row[2])) / 2
        writer.writerow([row[0], round(average, 2)])

Para las filas de calificaciones «Ana,8,9», «Ben,7,6» y "Lopez, Maria",10,8, las medias respectivas son 8,5; 6,5; 9,0. El lector elimina el entrecomillado CSV del valor del campo de entrada; el escritor vuelve a añadir las comillas necesarias en la salida. round() controla el valor numérico escrito, aunque no obliga a mostrar dos cifras decimales. Usa un formato como f"{average:.2f}" cuando quieras exactamente dos cifras.

Añade al final sin repetir la cabecera

Antes de abrir un archivo para añadir contenido al final, comprueba si necesita cabecera:

from pathlib import Path
p = Path("sales.csv")
needs_header = not p.exists() or p.stat().st_size == 0
with open(p, "a", newline="", encoding="utf-8") as f:
    writer = csv.writer(f)
    if needs_header:
        writer.writerow(["item", "quantity"])
    writer.writerow(["coffee", 4])

Un archivo existente pero vacío también necesita cabecera. Escribirla en cada ejecución coloca nombres de columnas en medio de los datos. Este patrón supone que un solo programa actualiza el archivo; comprobar su existencia no lo reserva frente a cambios de otros programas.

Puntos clave

  • Pasa una secuencia de campos a writerow() y una secuencia de filas a writerows().
  • El escritor convierte valores y gestiona el entrecomillado; None se convierte en un campo vacío.
  • Usa newline="" tanto para la salida como para la entrada CSV.
  • Añade una cabecera solo cuando el archivo sea nuevo o esté vacío.

3.3 Uso de nombres de columnas en código CSV

El código basado en posiciones, como row[2], depende del orden de las columnas. Un lector basado en diccionarios permite nombrar el valor que necesitas. Un diccionario relaciona claves con valores; aquí, la cabecera proporciona las claves y cada registro de datos proporciona sus valores.

Lee los campos por su nombre
import csv
with open("inventory.csv", newline="", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    rows = list(reader)

Para la cabecera product,stock,price y la fila notebook,12,2.50, el primer diccionario es {'product': 'notebook', 'stock': '12', 'price': '2.50'}. reader.fieldnames proporciona los nombres de la cabecera. Esta se consume automáticamente; llamar a next(reader) saltaría el primer registro de datos.

Usa row["stock"] para seleccionar las existencias, aunque cambie el orden de las columnas. Conviértelo con int() para comparar cantidades. Los valores siguen siendo cadenas; los nombres de las columnas no proporcionan tipos numéricos al lector.

Filtra y calcula el total

Supón que la tabla contiene 12 cuadernos a un precio de 2,50; 3 bolígrafos a 1,20; 0 grapadoras a 7,95 y 25 carpetas a 0,80.

low = [r for r in rows if int(r["stock"]) < 5]
value = sum(int(r["stock"]) * float(r["price"]) for r in rows)

low contiene las filas de los bolígrafos y las grapadoras. El valor es 53,6 u.m.: los cuadernos aportan 30, los bolígrafos 3,6, las grapadoras 0 y las carpetas 20. El filtro usa las existencias, mientras que el total usa tanto las existencias como el precio.

Distingue las claves ausentes de los valores ausentes

Los nombres de la cabecera deben coincidir exactamente. Name y name son claves distintas. Un espacio después de una coma puede pasar a formar parte de una cabecera; skipinitialspace=True elimina los espacios inmediatamente posteriores a los separadores.

Una cabecera name,quiz1,quiz2 con los datos Ben,7 produce {'name': 'Ben', 'quiz1': '7', 'quiz2': None}. La clave existe, pero falta su valor. int(None) lanza TypeError. Un campo presente pero vacío es "", y convertirlo lanza ValueError. En cambio, una clave ausente de la cabecera provoca KeyError al consultarla.

Con los datos Cara,1,2,3, los campos adicionales se agrupan como None: ['3']; los campos con nombre siguen conteniendo "Cara", "1" y "2". Comprueba la estructura de una fila cuando la exactitud de los totales dependa de todos los campos.

Escribe las columnas seleccionadas
with open("reorder.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(f, fieldnames=["product", "stock"])
    writer.writeheader()
    for r in low:
        writer.writerow({"product": r["product"], "stock": r["stock"]})

fieldnames establece el orden de salida, independientemente del orden del diccionario. Las claves ausentes del diccionario se convierten en campos vacíos. Las claves adicionales lanzan ValueError de forma predeterminada: pasar un diccionario de inventario que contenga price a este escritor de dos columnas falla. Construye el diccionario más pequeño como se muestra o elige extrasaction="ignore" cuando quieras descartar los campos adicionales.

Puntos clave

  • DictReader consume la cabecera y devuelve diccionarios con valores de tipo cadena.
  • Los nombres de la cabecera deben coincidir exactamente con las claves de consulta.
  • Un campo ausente toma None de forma predeterminada; un campo presente pero vacío es "".
  • Los campos adicionales se guardan bajo la clave None de forma predeterminada.
  • DictWriter necesita fieldnames para establecer el orden de las columnas.
  • Las claves de salida ausentes se convierten en campos vacíos; las claves inesperadas lanzan ValueError de forma predeterminada.
4

Maneja errores con try y except

Los nombres de archivo pueden ser incorrectos, el acceso puede denegarse y una columna numérica puede contener una palabra. Una excepción marca el punto donde la ejecución normal no puede continuar. Leerás informes de error, capturarás los problemas esperados y separarás las tareas que se realizan si todo va bien de la liberación de recursos. Seguir los errores a través de las llamadas a funciones te ayudará después a situar la recuperación donde se pueda tomar una decisión útil, como volver a intentar una lectura o informar de una fila rechazada.

4.1 Comprensión de un informe de error

Una excepción es un objeto que señala un problema durante la ejecución. Lanzarla interrumpe la ejecución normal. Si ningún manejador se ocupa de ella, Python termina el programa con una traza de la excepción, un informe de las llamadas que llevaron al error.

Empieza por abajo
def average(values):
    return sum(values) / len(values)

def report():
    scores = []
    print(average(scores))

report()

La traza termina con ZeroDivisionError: division by zero. Empieza ahí: el tipo identifica la clase de problema y el mensaje aporta detalles. La entrada inmediatamente superior apunta a la división en average(). Las entradas anteriores muestran la llamada desde report() y la llamada original a report(). La lista está vacía, por lo que su longitud es 0. La línea señalada como fallida es donde aparece el problema; la asignación anterior de la lista vacía explica cómo surgió.

Elige el tipo correspondiente
TipoCausa típica
ValueErrorint("3.5"): una cadena con un valor no aceptable
TypeErrorlen(5): una operación con una clase de objeto incorrecta
ZeroDivisionErrorDividir entre cero
IndexErrorLeer una posición de lista que no existe
KeyErrorConsultar una clave de diccionario ausente
NameErrorUsar un nombre no definido
AttributeErrorPedir a un objeto un atributo que no tiene

int("abc") recibe un tipo de entrada permitido, una cadena, pero no puede interpretar ese valor como un número entero. En cambio, "5" + 3 mezcla tipos incompatibles para la suma. Una cadena que contiene dígitos sigue siendo una cadena.

Las operaciones con archivos tienen tipos más específicos: FileNotFoundError para una ruta que no existe, PermissionError para un acceso denegado y FileExistsError al crear con "x" un archivo que ya existe. Abrir un directorio como un archivo normal puede lanzar IsADirectoryError. Descodificar bytes con una codificación incompatible puede lanzar UnicodeDecodeError.

Comprende el árbol genealógico

Las clases de excepción forman una jerarquía. Un manejador de una clase base puede capturar sus clases derivadas:

  • OSError es la clase base de errores habituales del sistema de archivos, incluidos FileNotFoundError y PermissionError.
  • LookupError es la clase base de IndexError y KeyError.
  • ArithmeticError es la clase base de ZeroDivisionError.
  • UnicodeDecodeError está bajo ValueError.

Estas ramas descienden de Exception, que desciende de BaseException. En cambio, KeyboardInterrupt y SystemExit descienden directamente de BaseException. Esa distinción permite que except Exception deje pasar la interrupción del usuario y la salida del programa.

Separa los problemas de sintaxis, ejecución y lógica

La ausencia de dos puntos o de un paréntesis de cierre puede impedir que Python analice un archivo de programa. El SyntaxError resultante ocurre antes de ejecutarlo, por lo que un try en ese mismo archivo no puede capturarlo. Una excepción de ejecución ocurre mientras se ejecuta código válido. Un error lógico produce una respuesta incorrecta sin lanzar necesariamente ninguna excepción, como dividir un total entre un conteo equivocado.

Puntos clave

  • Lee primero el tipo de excepción y el mensaje al final de una traza.
  • Usa las entradas de llamadas para seguir el valor que falla hasta su origen.
  • ValueError indica un valor no aceptable; TypeError indica un tipo inadecuado.
  • Un manejador de una excepción base también captura las clases de excepción derivadas.
  • Los errores de sintaxis, de ejecución y lógicos se producen de formas distintas.

4.2 Captura de un problema donde se puede manejar

Una sentencia try ejecuta código que puede fallar y ofrece una ruta de recuperación a determinadas excepciones. El manejador debe corresponder al problema que el programa espera y al que sabe responder.

Sigue el flujo
while True:
    try:
        age = int(input("Age: "))
        break
    except ValueError:
        print("Please enter a whole number, like 34.")
print("Next year you will be", age + 1)

Escribir «twenty» hace que int() lance ValueError. Python omite el resto del try, incluido break, y ejecuta el manejador correspondiente. Después, el bucle vuelve a preguntar. Escribir «34» permite que el try termine mediante break, por lo que el programa sale del bucle e imprime «Next year you will be 35».

Un manejador no reanuda la ejecución en la sentencia que falló. La ejecución continúa después de la sentencia try, salvo que el propio manejador cambie ese flujo. Si ningún manejador coincide, la excepción se propaga hacia fuera.

Maneja de forma distinta los fallos distintos
try:
    result = int(a) / int(b)
except ValueError:
    print("Both values must be whole numbers.")
except ZeroDivisionError:
    print("The second value cannot be 0.")

Una conversión incorrecta y un divisor cero necesitan mensajes distintos. Si la respuesta debe ser idéntica, agrupa los tipos en una tupla: except (ValueError, ZeroDivisionError):. Los paréntesis funcionan en todas las versiones de Python 3. Python 3.14 también permite una lista sin paréntesis cuando no hay una parte as; la forma con tupla sigue siendo clara entre versiones.

Python comprueba las cláusulas de arriba abajo y ejecuta la primera coincidencia. Sitúa FileNotFoundError antes de su clase base OSError si un archivo ausente necesita una respuesta especial. Invertirlas hace que el manejador especial sea inalcanzable.

Usa el mensaje sin ocultar otros errores de programación
try:
    quantity = int(text)
except ValueError as err:
    print("Cannot read quantity:", err)

err es el objeto de excepción; imprimirlo muestra su mensaje. type(err).__name__ da el nombre de su clase. Python elimina la vinculación de err del manejador cuando este termina, así que copia su mensaje en otra variable dentro del bloque si lo necesitas después.

Mantén pequeño el try. Sitúa los cálculos posteriores fuera del manejador de conversión cuando sus fallos necesiten otro tratamiento. except Exception: puede ocultar errores de programación, como una variable no definida. Un except: sin tipo es aún más amplio: también captura KeyboardInterrupt y SystemExit.

Intenta la operación, no una imitación aproximada

Comprobar text.isdigit() no comprueba todo lo que acepta int(). "-5" y " 34" no pasan esa prueba, pero se convierten correctamente; "²" la pasa, pero no se convierte con int(). Intentar la conversión y capturar ValueError usa las reglas de la propia conversión.

Haz algo visible o deja constancia al manejar datos incorrectos. Un except ValueError: pass vacío puede dejar que el programa continúe con resultados ausentes y sin explicar qué salió mal.

Puntos clave

  • Una excepción omite el código restante de try y ejecuta el primer manejador coincidente.
  • Usa tipos específicos y sitúa los manejadores de clases derivadas antes que los de clases base.
  • Agrupa los tipos en una tupla cuando su acción de recuperación sea la misma.
  • except ... as err da acceso al mensaje dentro del manejador.
  • Limita el try a lo necesario para que los mensajes describan la operación que realmente falla.
  • Intenta directamente la conversión numérica cuando necesites comprobar qué acepta.

4.3 Éxito, liberación de recursos y errores entre funciones

Una sentencia try puede separar la operación que puede fallar, la recuperación, las tareas que se realizan si todo va bien y la liberación de recursos. Una excepción también puede salir de una función y ser manejada por el código que la llamó.

Da un bloque propio a las tareas que se realizan si todo va bien
try:
    x = 10 / int(text)
except ValueError:
    print("not a number")
except ZeroDivisionError:
    print("zero")
else:
    print("result", x)
finally:
    print("done")

Con text = "4", el programa imprime «result 2.5» y «done». Con "abc", imprime «not a number» y «done»; con "0", imprime «zero» y «done».

else se ejecuta cuando el try termina normalmente sin una excepción. No se ejecuta después de que un manejador se recupere de un error. También se omite cuando return, break o continue sale antes de tiempo del try. Los errores lanzados dentro de else no son capturados por las cláusulas except anteriores de esa sentencia, por lo que las tareas de éxito no comparten por accidente los manejadores de la operación que puede fallar.

Libera recursos en todas las rutas de salida

finally se ejecuta cuando el control sale de la sentencia: después de que todo vaya bien, tras una excepción manejada y antes de que una excepción no manejada siga propagándose. También se ejecuta antes de completar un retorno pendiente.

def label():
    try:
        return "from try"
    finally:
        print("finally ran")

value = label()
print(value)

Esto imprime «finally ran» y después «from try». El retorno esperaba mientras se liberaban los recursos. Para los archivos, with ya proporciona el cierre, por lo que normalmente elimina la necesidad de cerrarlos manualmente en finally.

No incluyas una salida como return, break o continue en finally. Salir así del bloque de liberación de recursos puede descartar una excepción pendiente o sustituir un retorno. Python 3.14 y posteriores emiten un SyntaxWarning para este patrón. Limita ese bloque a liberar recursos.

Sigue una excepción hasta el código que realizó la llamada
def read_scores(path):
    with open(path, encoding="utf-8") as f:
        return [int(line) for line in f]

try:
    scores = read_scores("scores.txt")
except FileNotFoundError:
    print("The score file is missing.")

Si la apertura falla, read_scores() no tiene manejador, por lo que FileNotFoundError se propaga hasta la llamada dentro del try externo. El código que realizó la llamada la maneja e imprime el mensaje. Si una línea no es un número entero, un ValueError sigue la misma ruta, pero el manejador de archivos ausentes no coincide con él.

Elige el nivel que pueda dar una respuesta útil

Una función de lectura puede saber cómo obtener datos, pero no si un archivo ausente debe provocar otro intento, la omisión de una tarea o una detención controlada. Dejar que la excepción llegue al código que realiza la llamada e interactúa con el usuario deja allí esa decisión. Capturarla demasiado pronto y devolver una lista vacía puede ocultar la diferencia entre un archivo vacío y una lectura fallida.

Puntos clave

  • else solo se ejecuta después de que el cuerpo de try termine normalmente.
  • finally se ejecuta antes de que salga el control, incluso en un retorno o ante una excepción no manejada.
  • Una excepción en else queda fuera de los manejadores anteriores de esa sentencia.
  • Evita salidas de finally que puedan descartar errores o retornos pendientes.
  • Las excepciones no manejadas se propagan a través de las llamadas hasta un manejador externo coincidente.

4.4 Recuperación de errores en archivos y filas

Un programa gestiona un fallo de forma controlada cuando responde a un problema de manera controlada y útil. Puede volver a preguntar, informar de una fila omitida o detenerse con un mensaje claro. Elige esa respuesta según el uso que se vaya a dar al resultado.

Vuelve a intentarlo si el archivo no existe
while True:
    name = input("File name: ").strip()
    try:
        with open(name, encoding="utf-8") as f:
            text = f.read()
    except FileNotFoundError:
        print(f"No file named '{name}'. Please try again.")
    else:
        break
print(len(text.splitlines()), "lines")

Una apertura fallida omite la asignación y llega al manejador. El bucle vuelve a preguntar. Una lectura correcta llega a else, termina el bucle y deja text disponible para el conteo final. with cierra el archivo en cualquiera de las salidas de un bloque en el que se haya entrado.

Para distintos problemas con archivos, usa FileNotFoundError, después PermissionError y luego un manejador general de OSError si otros errores del sistema de archivos necesitan respuesta. Las cláusulas específicas deben ir primero. Descodificar bytes incorrectos es otro problema; un mensaje sobre una ruta ausente no lo describiría.

Maneja cada fila de datos por separado

Para un resumen rápido de ventas, supón que las filas CSV después de la cabecera son coffee,4, tea,two, muffin,3, cookie, y juice,5.

import csv
total = 0
skipped = 0
with open("sales.csv", newline="", encoding="utf-8") as f:
    reader = csv.reader(f)
    next(reader, None)
    for row in reader:
        try:
            if len(row) != 2:
                raise ValueError("expected two fields")
            quantity = int(row[1])
        except ValueError as err:
            skipped += 1
            print(f"sales.csv, ending line {reader.line_num}: {err}")
        else:
            total += quantity
print("Total:", total, "Skipped:", skipped)

Las cantidades válidas suman 12. Se rechazan la palabra «two» y la cantidad vacía, por lo que el conteo de filas omitidas es 2. La comprobación de la fila también convierte un número inesperado de campos en un error de datos comunicado antes de acceder por índice. Situar try dentro del bucle permite procesar el siguiente registro después de que uno falle; situar el bucle dentro de un único try haría que se saliera del bucle en el primer fallo.

Indica las ubicaciones con precisión

Para los cinco registros de una sola línea, los valores incorrectos terminan en las líneas 3 y 5 del archivo. Aquí enumerate(reader, start=2) coincidiría con esos números de línea, pero un salto de línea entrecomillado hace que un registro CSV abarque más de una línea. reader.line_num indica cuántas líneas físicas ha consumido el lector. Llamarla línea final mantiene la precisión de los mensajes para registros de varias líneas.

Decide si un resultado parcial es aceptable

Un conteo exploratorio rápido puede permitir omisiones comunicadas. Un total financiero o de calificaciones puede necesitar todos los registros: detente y pide datos corregidos en lugar de presentar un total parcial como completo. Indica el archivo, la ubicación y el problema para que pueda corregirse.

Después de import sys, sys.exit("Could not open sales.csv") escribe el mensaje en la salida de errores y termina con el código de salida 1. Lanza SystemExit, que except Exception no captura. Mantén los manejadores específicos para que un error de programación ajeno no se identifique erróneamente como un problema de archivo.

Puntos clave

  • Elige volver a intentar, saltar o detener según la tarea.
  • Sitúa la recuperación por fila dentro del bucle para continuar después de una fila incorrecta.
  • Informa de los registros omitidos e identifica claramente los resultados parciales.
  • Los números de registro CSV pueden diferir de los números de línea física.
  • sys.exit(message) termina con un mensaje de error y el código de salida 1.
  • Usa manejadores específicos para que el mensaje corresponda al problema real.
5

Lanza tus propias excepciones

Las funciones necesitan una forma clara de informar de datos de entrada que no pueden manejar. Lanzar una excepción impide que una operación fallida produzca un resultado engañoso y permite que el código que realizó la llamada elija una respuesta. Elegirás tipos y mensajes con sentido, propagarás un error existente y conservarás su causa al convertirlo en otro. Un patrón breve de clase personalizada da al programa su propio tipo de error cuando el código que realiza las llamadas necesita distinguir un problema de otro.

5.1 Rechazo de datos de entrada con raise

Una función debe avisar cuando no pueda producir un resultado válido. raise inicia una excepción en ese punto para que la ruta no válida no continúe como si la operación hubiera tenido éxito.

Comprueba antes de calcular
def withdraw(balance, amount):
    if amount <= 0:
        raise ValueError(f"amount must be positive, got {amount}")
    if amount > balance:
        raise ValueError(f"amount {amount} is more than the balance {balance}")
    return balance - amount

withdraw(100, 30) devuelve 70. withdraw(100, 150) lanza un error sobre el saldo; withdraw(100, -5) lanza un error sobre un importe no positivo. Ninguna de las llamadas que fallan llega a la resta.

Una excepción lanzada sigue las mismas reglas de manejo que un error incorporado. Si un manejador coincidente dentro de la función la captura, la ejecución puede continuar allí. En caso contrario, la excepción sale de la función y llega al código que la llamó. Si no se encuentra ningún manejador, Python muestra una traza de la excepción.

Deja que el código que realiza la llamada elija la respuesta
balance = 100
amount = 150
try:
    balance = withdraw(balance, amount)
except ValueError as err:
    print(f"Cannot withdraw: {err}")

La función informa de por qué no puede retirar el importe. El código que realiza la llamada decide mostrar un mensaje. Como la llamada a la función falla antes de devolver un valor, la asignación no sustituye el saldo anterior por un resultado. Otro código que la llamara podría pedir un importe menor o cancelar una transacción sin modificar la función.

En cambio, imprimir una advertencia dentro de la función y devolver None puede permitir que el código que la llama lleve un valor no válido a un cálculo posterior. Lanzar una excepción mantiene el fallo unido a su causa y proporciona al código que realiza la llamada una ruta de error diferenciada.

Elige un tipo con sentido
ProblemaTipo adecuado
Clase de entrada correcta, valor no aceptableValueError
Clase de objeto incorrecta para la operaciónTypeError

Un importe numérico negativo tiene un valor no aceptable. Una lista proporcionada donde se necesita un número tiene un tipo inadecuado. El tipo de excepción forma parte del comportamiento de la función: el código que la llama lo usa para seleccionar manejadores. No elijas un tipo solo porque te resulte familiar.

Escribe un mensaje útil

Un mensaje debe indicar qué se esperaba y qué se recibió. f"age must be between 0 and 130, got {age}" orienta hacia una corrección. Un mensaje como «error» no aporta detalles útiles. Centra el mensaje en la operación fallida; el código que interactúa con el usuario puede añadir el contexto general.

raise ValueError("amount must be positive") crea una excepción con un mensaje. raise ValueError también es válido y crea una sin mensaje. Una cadena simple no es una excepción: raise "error" lanza TypeError porque los objetos lanzados deben derivar de BaseException.

Puntos clave

  • Lanza una excepción en el punto donde una función no pueda continuar correctamente.
  • Usa ValueError para un valor no aceptable y TypeError para un tipo inadecuado.
  • Incluye la entrada esperada y el valor recibido en un mensaje útil.
  • Deja que el código que realiza la llamada decida cómo responder a la operación fallida.

5.2 Propagación y denominación de excepciones

A veces una función detecta un error, pero no puede terminar de manejarlo. Puede necesitar propagar el mismo error, convertirlo en otro más útil o dar a un problema concreto del programa su propio tipo de excepción.

Vuelve a lanzar el error actual
def read_text(path):
    try:
        with open(path, encoding="utf-8") as f:
            return f.read()
    except FileNotFoundError:
        print(f"Missing: {path}")
        raise

El raise sin argumentos dentro del manejador vuelve a lanzar la excepción actual. Imprimir solo un mensaje terminaría el manejador y haría que la función devolviera None; relanzarla hace visible la lectura fallida al código que realizó la llamada. Un raise sin argumentos necesita una excepción activa que volver a lanzar.

Convierte la excepción conservando la causa
def read_price(row):
    try:
        text = row["price"]
    except KeyError as err:
        raise ValueError("row has no 'price' column") from err
    return float(text)

Una clave ausente se convierte en un ValueError con un mensaje sobre la fila. from err registra el KeyError original como su causa directa. La traza muestra el error original, el vínculo entre ambos y el nuevo error. El código que realiza la llamada puede manejar el tipo resultante mientras la depuración conserva la causa de nivel inferior.

Este manejador se limita a la consulta por clave. Un valor presente como "free" falla después en float(text) con su propio ValueError; no se informa falsamente de que falta una columna.

Define un tipo distinto
class InsufficientFundsError(ValueError):
    pass

Este patrón crea una clase de excepción personalizada. Por convención, el nombre termina en Error. El nombre entre paréntesis es su clase base, por lo que esta clase es un tipo de ValueError.

def withdraw(balance, amount):
    if amount > balance:
        raise InsufficientFundsError(
            f"balance {balance}, requested {amount}"
        )
    return balance - amount

try:
    withdraw(100, 150)
except InsufficientFundsError as err:
    print("Not enough money:", err)

El programa imprime «Not enough money: balance 100, requested 150». El código que realiza la llamada puede distinguir la falta de fondos de otro valor no válido. Si apareciera un manejador de ValueError antes de este manejador específico, el de la clase base lo capturaría primero.

Elige la clase base según el manejo deseado

Derivar de ValueError permite que tanto un manejador específico como otro más amplio de errores de valor capturen el tipo personalizado. Derivar directamente de Exception crea una rama separada de errores ordinarios, por lo que except ValueError no lo capturaría. Un tipo personalizado es útil cuando el código que realiza las llamadas necesita una respuesta distinta; un tipo incorporado y un mensaje claros bastan cuando no la necesita.

Puntos clave

  • Un raise sin argumentos en un manejador propaga la excepción actual.
  • raise NewError(...) from err registra el error original como causa directa.
  • Una excepción personalizada proporciona al código que realiza la llamada un tipo de problema distinto.
  • La clase base determina qué manejadores más amplios pueden capturar el error personalizado.
  • Sitúa un manejador personalizado específico antes del manejador de su clase base.

Ejemplos de Archivos y excepciones en Python

5 Lecciones Interactivas

1

Convierte un archivo de texto en un informe filtrado

13 pasos
Lee líneas, elige modos de archivo y guarda registros seleccionados dejando claro cuándo permanecen abiertos los archivos.
  1. 1
    IntroducciónLee, decide y guarda

    Un registro de soporte contiene un evento por línea. Quieres un archivo nuevo que contenga solo los eventos que necesitan atención. Esa tarea combina lectura, comprobaciones de cadenas y escritura.

    Primero observa cómo proporciona texto un archivo. Después construye el filtro en pasos pequeños, manteniendo la entrada separada de la salida y dejando que with cierre ambos archivos cuando termine el procesamiento.

  2. 2
    ExplicaciónUn archivo proporciona cadenas

    Supón que events.txt contiene "INFO Ready\nERROR Queue full\n". Abrirlo crea un objeto de archivo, no una copia de su texto.

    f.readline() devuelve "INFO Ready\n". Una segunda llamada devuelve "ERROR Queue full\n". Una tercera devuelve "" porque el archivo se ha agotado. El salto de línea permanece unido a la línea devuelta; el texto numérico también seguiría siendo texto hasta convertirlo explícitamente.

  3. 3
    DesafíoElige un método de lectura

    Un registro de actividad puede ser mucho mayor que la memoria disponible. Solo necesitas examinar cada línea una vez. ¿Cómo deberías leerlo y por qué?

    ---reveal---

    Recorre directamente el archivo abierto con for line in f:. Proporciona una línea cada vez sin necesitar primero una cadena o lista del archivo completo. Llamar a read() o readlines() cargaría en memoria el contenido restante.

  4. 4
    EjemploMantén la lectura dentro del bloque
    with open("events.txt", encoding="utf-8") as f:
        first = f.readline()
    print(first.rstrip("\n"))
    

    La lectura ocurre mientras el archivo está abierto. Salir del bloque con sangría lo cierra; la impresión posterior usa la cadena guardada. Por eso una operación sobre first puede realizarse después, mientras que otro f.readline() no.

  5. 5
    DesafíoPredice la liberación de recursos tras un error

    Dentro de ese bloque de archivo, supón que int("oops") lanza ValueError. El código que lo rodea no tiene manejador. ¿Permanece abierto el archivo? ¿Oculta with el error?

    ---reveal---

    El archivo se cierra cuando la ejecución sale del bloque en el que había entrado. El error sigue propagándose y produce una traza de excepción si nada lo captura. La liberación automática de recursos controla cuánto tiempo permanece abierto el archivo; se necesitaría un manejador except para recuperarse.

  6. 6
    ExplicaciónElige el comportamiento de la salida

    El informe filtrado debe sustituir a uno anterior, así que abre una ruta de salida distinta con "w". Ese modo vacía inmediatamente un archivo existente.

    Para un historial de actividad que conserve ejecuciones anteriores, usa "a". Si hay que proteger un informe existente frente a la sustitución, usa "x" y maneja FileExistsError. La creación de archivos sigue necesitando que existan las carpetas que los contienen.

  7. 7
    EjemploEscribe exactamente una línea

    Para escribir una línea seleccionada, conserva su terminador original:

    dst.write(line)
    

    Si la has limpiado con strip(), vuelve a añadir el terminador:

    dst.write(cleaned + "\n")
    

    write() no añade separadores. print(cleaned, file=dst) es otra forma de añadir un salto de línea, mientras que writelines() sigue esperando que las cadenas proporcionadas contengan los terminadores necesarios.

  8. 8
    DesafíoPredice dos ejecuciones

    Al principio no existe el archivo y un programa se ejecuta dos veces. Cada ejecución abre "runs.txt" en modo de adición al final y llama a f.write("OK"). ¿Qué texto se guarda?

    ---reveal---

    El archivo contiene "OKOK". El modo de adición al final conserva la primera ejecución, pero ni el modo ni write() añaden un salto de línea. Escribir "OK\n" produciría una línea por ejecución. Abrir con "w" dejaría solo el último "OK".

  9. 9
    EjemploLimpia antes de seleccionar

    Nuestro registro de actividad usa la primera palabra como nivel. Empieza cada iteración con:

    cleaned = line.strip()
    if not cleaned:
        continue
    level = cleaned.split(maxsplit=1)[0]
    

    La comprobación de línea vacía evita acceder por índice a una lista vacía. Conservar por separado la line original permite que la salida mantenga su espaciado. Solo se usa la copia limpia para identificar el nivel.

  10. 10
    DesafíoComprueba la parte adecuada

    El registro incluye «INFO ERROR counter reset» y «ERROR Queue full». ¿Qué comprobación de nivel guarda solo el segundo registro?

    ---reveal---

    Comprueba level == "ERROR" después de extraer la primera palabra. Buscar "ERROR" en cualquier posición también guardaría el registro informativo porque la palabra aparece en su mensaje. El formato indica dónde encontrar la categoría que estás seleccionando.

  11. 11
    EjemploMonta el filtro
    count = 0
    with open("events.txt", encoding="utf-8") as src, open("urgent.txt", "w", encoding="utf-8") as dst:
        for line in src:
            cleaned = line.strip()
            if not cleaned:
                continue
            if cleaned.split(maxsplit=1)[0] == "ERROR":
                dst.write(line)
                count += 1
    print(count, "saved")
    

    El contador cambia solo cuando se escribe un registro. Ambos archivos se cierran antes de imprimir el conteo.

  12. 12
    DesafíoDiagnostica la pérdida del origen

    Alguien cambia el nombre de salida a "events.txt" y mantiene "w". ¿Por qué el filtro corre ahora el riesgo de no guardar nada, aunque el origen se haya abierto primero?

    ---reveal---

    La segunda apertura vacía el mismo archivo subyacente antes de que el bucle lo lea. El primer objeto de archivo no ha guardado una copia separada del texto anterior. Vuelve a usar una ruta de salida distinta para que la transformación no pueda borrar su entrada al abrir.

  13. 13
    RepasoSigue una tarea con archivos antes de ejecutarla

    Para una transformación de archivos, sigue cuatro decisiones: de dónde viene la entrada, cuánto texto se lee a la vez, qué selecciona un registro y qué hace la apertura de la salida con los datos existentes.

    Después comprueba los límites de los bloques. Las operaciones con archivos necesitan manejadores abiertos; las cadenas, listas y totales guardados pueden usarse después de cerrarlos.

2

Localiza los datos del proyecto desde cualquier carpeta de inicio

9 pasos
Sigue rutas relativas, construye rutas relativas al archivo de programa y prepara carpetas con pathlib.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónLocaliza la carpeta de partida
  2. 2
    EjemploSigue un inicio de ejecución
  3. 3
    DesafíoCambia la carpeta de inicio
  4. 4
    ConsejoExamina antes de cambiar la ruta
  5. 5
    EjemploConstruye desde el archivo de programa
  6. 6
    ExplicaciónPrepara un destino
  7. 7
    DesafíoExamina un nombre y busca coincidencias
  8. 8
    DesafíoComprueba una solución propuesta
  9. 9
    RepasoSepara ubicación y disponibilidad
3

Lee una tabla y escribe un informe con columnas por nombre

13 pasos
Interpreta CSV entrecomillado, convierte campos numéricos y exporta columnas seleccionadas en un orden controlado.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónConserva la estructura de la tabla
  2. 2
    EjemploLee un registro entrecomillado
  3. 3
    EjemploAbre y convierte
  4. 4
    DesafíoReconoce una fila incompleta
  5. 5
    EjemploEscribe valores como campos
  6. 6
    DesafíoMantén unido un campo
  7. 7
    ExplicaciónUsa la cabecera como claves
  8. 8
    EjemploFiltra por existencias
  9. 9
    DesafíoDistingue lo ausente de lo vacío
  10. 10
    EjemploExporta las columnas seleccionadas
  11. 11
    DesafíoAñade un lote posterior
  12. 12
    ConsejoAjusta los separadores y las codificaciones
  13. 13
    RepasoComprueba la estructura y el significado
4

Sigue un error desde una fila incorrecta hasta una respuesta útil

15 pasos
Lee una traza de excepción, selecciona manejadores y distingue entre reintentar un archivo y recuperarte dentro de un bucle de filas.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónElige de qué fallos se puede recuperar el programa
  2. 2
    EjemploEmpieza por el tipo de excepción
  3. 3
    DesafíoReconoce un fallo distinto
  4. 4
    EjemploCaptura solo el error de conversión esperado
  5. 5
    DesafíoOrdena los manejadores relacionados
  6. 6
    ExplicaciónDa tareas distintas al éxito y a la liberación de recursos
  7. 7
    DesafíoSigue un error sin manejador coincidente
  8. 8
    ConexiónDeja decidir al código que realiza la llamada
  9. 9
    EjemploMantén la recuperación dentro del bucle de registros
  10. 10
    EjemploSigue tres registros
  11. 11
    DesafíoCambia el límite del bucle
  12. 12
    ConsejoIndica la ubicación correctamente
  13. 13
    DesafíoElige un resultado completo
  14. 14
    EjemploTermina con un código de error
  15. 15
    RepasoSitúa cada respuesta en el nivel adecuado
5

Diseña el comportamiento de una función ante errores

10 pasos
Valida una solicitud, lanza errores útiles y conserva las distinciones y causas para el código que realiza la llamada.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónDa al fallo una ruta clara
  2. 2
    EjemploRechaza solicitudes no válidas
  3. 3
    DesafíoSigue una asignación fallida
  4. 4
    ExplicaciónAjusta el tipo al problema
  5. 5
    EjemploDa un nombre propio a la falta de plazas
  6. 6
    DesafíoMantén accesible la respuesta específica
  7. 7
    EjemploReacciona y propaga el error
  8. 8
    EjemploConvierte un fallo de nivel inferior
  9. 9
    DesafíoElige la relación adecuada
  10. 10
    RepasoMantén el error útil para el código que realiza la llamada

Ejercicios de Archivos y excepciones en Python

50 Preguntas de Práctica en 5 sets

Set 1: Elección de métodos y manejo de fallos esperados10 Preguntas de Práctica

Pregunta 1 de 10

Un registro de actividad tiene las líneas "09:10 INFO ERROR count reset" y "09:12 ERROR Network down". El nivel es el segundo campo separado por espacios en blanco. ¿Qué condición selecciona solo los registros de nivel de error?
  1. "ERROR" in line
  2. line.startswith("ERROR")
  3. line.split()[2] == "ERROR"
  4. line.split()[1] == "ERROR"
Mostrar respuestaOcultar respuesta
Respuesta: D
Al dividir, la hora queda en la posición 0 y el nivel en la posición 1, por lo que comprobar el segundo campo selecciona solo el registro de nivel de error. Buscar en cualquier posición también encontraría «ERROR» en el mensaje informativo. La posición del nivel es independiente del texto del mensaje.

Pregunta 2 de 10

Un archivo contiene "12\n15\n". ¿Qué pareja resulta de first = f.read() seguido de second = f.read() sobre un mismo lector recién abierto?
  1. first == "12\n15\n", second == ""
  2. first == "12\n", second == "15\n"
  3. first == "12\n15\n", second == first
  4. first == [12, 15], second == []
Mostrar respuestaOcultar respuesta
Respuesta: A
El primer read() consume todo el texto restante, incluido el salto de línea final. El segundo empieza al final y devuelve una cadena vacía. Leer no reinicia la posición ni convierte los dígitos en números enteros, por lo que no se obtiene otra lectura completa ni una lista numérica.

Pregunta 3 de 10

En Windows, ¿por qué puede el literal de cadena de Python "C:\new\tasks.txt" no identificar el archivo deseado?
  1. El nombre de la unidad hace que la ruta sea relativa a ella.
  2. Las barras invertidas solo funcionan en rutas relativas.
  3. Las barras invertidas inician escapes de salto de línea y tabulación.
  4. Una ruta absoluta debe empezar con una barra normal.
Mostrar respuestaOcultar respuesta
Respuesta: C
En una cadena normal, \n se convierte en un salto de línea y \t en una tabulación, lo que cambia el texto de la ruta almacenado. Usa una cadena sin procesar, barras invertidas duplicadas o barras normales para conservar los caracteres deseados. Una ruta que incluye una unidad no se vuelve relativa por usar barras invertidas.

Pregunta 4 de 10

Un archivo empieza con city,visitors y Mesa,24. Después de reader = csv.DictReader(f), el programa llama una vez a next(reader) y después recorre el lector con un bucle. ¿Por qué no aparece Mesa en ese bucle?
  1. El lector trata los valores numéricos como nombres de campos.
  2. La llamada consumió el primer registro de datos.
  3. El lector no puede usar una cabecera en minúsculas.
  4. El bucle salta los registros con nombres sin comillas.
Mostrar respuestaOcultar respuesta
Respuesta: B
DictReader ya usa la cabecera como claves, por lo que el primer elemento que devuelve es el diccionario de datos de Mesa. Llamar a next(reader) consume ese elemento antes de que empiece el bucle. Un csv.reader normal necesita saltar la cabecera por separado; copiar aquí ese paso hace que se pierdan datos.

Pregunta 5 de 10

La primera línea es label;count, pero el lector CSV predeterminado devuelve ["label;count"]. ¿Qué ajuste del lector corresponde a este archivo?
  1. skipinitialspace=True
  2. delimiter=","
  3. quoting=csv.QUOTE_ALL
  4. delimiter=";"
Mostrar respuestaOcultar respuesta
Respuesta: D
El archivo separa los campos con punto y coma, por lo que delimiter=";" hace que el lector reconozca dos campos. Eliminar los espacios después de los separadores no cambia qué separador se reconoce. Los ajustes de entrecomillado tampoco hacen que el punto y coma actúe como la coma delimitadora predeterminada.

Pregunta 6 de 10

¿Qué se imprime?

try:
    value = 18 / int("0")
except ZeroDivisionError:
    print("zero")
else:
    print("success")
finally:
    print("closed")
  1. «success», después «closed»
  2. «zero», después «closed»
  3. «zero», después «success»
  4. «closed», después «zero»
Mostrar respuestaOcultar respuesta
Respuesta: B
Convertir "0" tiene éxito, pero la división lanza ZeroDivisionError. Su manejador imprime «zero», se omite else y finally imprime «closed». Manejar el error no convierte la ejecución original de try en una finalización normal a efectos de else.

Pregunta 7 de 10

Se necesita un total completo de pagos de subvenciones. Un CSV tiene un importe no válido entre 200 registros. ¿Por qué es una mala decisión de recuperación saltarlo y mostrar el resto como total completo?
  1. El total omite un pago necesario sin indicarlo.
  2. Un fallo de conversión impide volver a abrir el archivo.
  3. La omisión cambia todos los importes de los pagos restantes.
  4. Un CSV no puede contener filas válidas y no válidas a la vez.
Mostrar respuestaOcultar respuesta
Respuesta: A
Todos los pagos son necesarios, por lo que omitir un registro no válido hace que el total esté incompleto. El programa debe detenerse e informar del registro que necesita corrección o identificar claramente un resultado parcial permitido. Un fallo de conversión de una fila no hace por sí solo que el archivo sea ilegible.

Pregunta 8 de 10

Se produce un FileNotFoundError en un try. El primer manejador es except OSError: print("file problem") y el segundo es except FileNotFoundError: print("missing"). ¿Qué se imprime?
  1. «missing»
  2. «file problem», después «missing»
  3. «file problem»
  4. Ningún manejador coincide.
Mostrar respuestaOcultar respuesta
Respuesta: C
FileNotFoundError deriva de OSError, por lo que el primer manejador ya coincide e imprime «file problem». Python ejecuta solo la primera cláusula coincidente. Sitúa primero el manejador específico cuando un archivo ausente necesite una respuesta distinta de la de otros errores del sistema de archivos.

Pregunta 9 de 10

Dentro de un bloque except ValueError:, ¿qué sentencia propaga la misma excepción activa al código que realizó la llamada?
  1. return
  2. raise
  3. continue
  4. pass
Mostrar respuestaOcultar respuesta
Respuesta: B
Un raise sin argumentos vuelve a lanzar la excepción activa y mantiene visible la operación fallida fuera del manejador actual. pass simplemente no hace nada y permite que ese manejador termine normalmente. Un retorno saldría de la función normalmente en lugar de propagar el error original.

Pregunta 10 de 10

¿Qué se imprime?

def reserve(n):
    if n <= 0:
        raise ValueError("positive count required")
    return n * 2
result = 7
try:
    result = reserve(0)
except ValueError:
    print(result)
  1. 7
  2. 0
  3. None
  4. 14
Mostrar respuestaOcultar respuesta
Respuesta: A
reserve(0) lanza una excepción antes de devolver un valor, por lo que la asignación a result no se completa. El valor anterior, 7, permanece y el manejador lo imprime. Una excepción no hace que una llamada fallida devuelva None; interrumpe la expresión.
Set 2: Lectura de archivos y seguimiento de programas pequeños10 Preguntas de Práctica

Guarda esta unidad para ver todas las respuestas y practicar cada set.

Pregunta 1 de 10

¿Qué fila produce writer.writerow("Leo") con la coma como delimitador predeterminado?
  1. Leo
  2. "Leo"
  3. L,e,o
  4. L e o
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 2 de 10

Un archivo contiene "oak\npine". Justo después de abrirlo para leer, ¿qué devuelve f.readline()?
  1. "oak"
  2. ["oak\n", "pine"]
  3. "oak\n"
  4. "oak\npine"
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 3 de 10

El bloque termina normalmente. ¿Qué se imprime?

with open("memo.txt", encoding="utf-8") as f:
    text = f.read()
print(f.closed)
  1. False
  2. True
  3. None
  4. text
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 4 de 10

Un programa debe añadir un mensaje de ejecución a un registro de actividad conservando todos los mensajes anteriores. ¿Qué modo de archivo de texto debe usar?
  1. "a"
  2. "w"
  3. "r"
  4. "x"
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 5 de 10

Una terminal trabaja en /work/lab. Ejecuta python tools/count.py, que abre "inputs/list.txt". ¿Qué ubicación absoluta solicita esa ruta relativa?
  1. /work/lab/tools/inputs/list.txt
  2. /work/inputs/list.txt
  3. /inputs/list.txt
  4. /work/lab/inputs/list.txt
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 6 de 10

Para p = Path("exports/week/report.csv"), ¿cuál es el valor de p.stem?
  1. ".csv"
  2. "report"
  3. "report.csv"
  4. "exports/week"
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 7 de 10

Con el csv.reader predeterminado, ¿qué lista se lee del registro "River, West",6,8?
  1. ['River, West', '6', '8']
  2. ['River, West', 6, 8]
  3. ['\"River', ' West\"', '6', '8']
  4. ['River', 'West', '6', '8']
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 8 de 10

Un campo de cantidad CSV contiene la cadena "many". ¿Qué excepción lanza int(row["quantity"])?
  1. TypeError
  2. KeyError
  3. IndexError
  4. ValueError
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 9 de 10

¿Qué se imprime?

def read_count(text):
    return 12 / int(text)
try:
    result = read_count("0")
    print("read")
except ValueError:
    print("bad text")
except ZeroDivisionError:
    print("zero")
print("end")
  1. «read», después «end»
  2. «bad text», después «end»
  3. «zero», después «end»
  4. «zero», después «read»
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 10 de 10

Una función acepta un número entero de páginas, pero no puede procesar una cantidad inferior a 1. Para la entrada -2, ¿qué excepción y mensaje son adecuados?
  1. TypeError("pages must be positive, got -2")
  2. ValueError("pages must be positive, got -2")
  3. IndexError("pages must be positive, got -2")
  4. NameError("pages must be positive, got -2")
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Set 3: Procesamiento de archivos y rutas de recuperación10 Preguntas de Práctica

Guarda esta unidad para ver todas las respuestas y practicar cada set.

Pregunta 1 de 10

¿Qué excepción lanza la consulta de diccionario {"east": 4}["west"]?
  1. IndexError
  2. ValueError
  3. KeyError
  4. NameError
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 2 de 10

Un archivo contiene solo «bad». ¿Qué se imprime?

try:
    with open("one.txt", encoding="utf-8") as f:
        value = int(f.readline())
except ValueError:
    print(f.closed)
  1. False
  2. True
  3. Una traza de excepción de NameError.
  4. Una traza de excepción de FileNotFoundError.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 3 de 10

Se escribe un archivo nuevo con f.writelines(["red", "blue\n"]) y después se abre otra vez en modo de adición al final para escribir "green\n". ¿Qué texto contiene?
  1. "redblue\ngreen\n"
  2. "red\nblue\ngreen\n"
  3. "green\n"
  4. "redbluegreen\n"
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 4 de 10

Las carpetas results y results/daily no existen. ¿Qué debe ejecutarse antes de escribir con Path("results/daily/run.txt").write_text("ok", encoding="utf-8")?
  1. Path("results/daily").mkdir(exist_ok=True)
  2. Path("results/daily/run.txt").mkdir(parents=True)
  3. Path("results/daily").exists()
  4. Path("results/daily").mkdir(parents=True, exist_ok=True)
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 5 de 10

Un programa que añade al final escribe una cabecera solo cuando not p.exists(). La ruta existe, pero tiene cero bytes. ¿Qué condición proporciona también a este archivo la cabecera que necesita?
  1. p.exists() and p.stat().st_size > 0
  2. not p.exists() and p.stat().st_size == 0
  3. not p.exists() or p.stat().st_size == 0
  4. p.exists()
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 6 de 10

Un DictReader predeterminado tiene la cabecera name,first,second y lee Inez,5. ¿Qué valor se almacena bajo "second" y qué ocurre al pasarlo a int()?
  1. None; lanza TypeError.
  2. ""; lanza ValueError.
  3. "5"; devuelve 5.
  4. No hay clave; lanza KeyError.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 7 de 10

¿Qué recibe el código que realiza la llamada y qué se imprime primero?

def choose():
    try:
        return 11
    finally:
        print("leaving")
x = choose()
  1. Recibe None; primero se imprime «leaving».
  2. Recibe 11; no se imprime nada.
  3. Recibe «leaving»; primero se imprime 11.
  4. Recibe 11; primero se imprime «leaving».
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 8 de 10

Un resumen CSV debe informar de las filas numéricas mal formadas y continuar con los registros posteriores. ¿Dónde debe situarse el try/except ValueError de la conversión?
  1. Alrededor de todo el bucle, fuera de su cuerpo.
  2. Dentro del bucle, alrededor de la conversión de cada fila.
  3. Después del bucle, alrededor de la impresión final.
  4. Solo alrededor de la llamada inicial a open().
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 9 de 10

Dado class LimitError(ValueError): pass, se lanza un LimitError. ¿Qué ocurre si except ValueError: aparece antes de except LimitError:?
  1. Ninguna cláusula coincide con el tipo personalizado.
  2. Solo se ejecuta el manejador de ValueError.
  3. Ambos manejadores se ejecutan en el orden escrito.
  4. Solo se ejecuta el manejador de LimitError.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 10 de 10

Después de limpiar y saltar las líneas en blanco, un analizador establece parts = line.split(maxsplit=2). Los registros deben tener fecha, nivel y mensaje, pero algunos solo contienen una fecha. ¿Qué comprobación debe preceder a parts[1] y parts[2]?
  1. len(parts) == 3
  2. line.endswith("\n")
  3. len(line) > 3
  4. " " in parts[0]
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Set 4: Diagnóstico de datos incompletos y manejadores engañosos10 Preguntas de Práctica

Guarda esta unidad para ver todas las respuestas y practicar cada set.

Pregunta 1 de 10

Al final del archivo, ¿qué devuelve f.readline()?
  1. None
  2. "\n"
  3. []
  4. ""
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 2 de 10

data.txt contiene tres registros. Un programa lo abre con "r", después abre la misma ruta con "w" y solo entonces empieza a leer mediante el primer manejador. ¿Por qué existe el riesgo de perder la entrada?
  1. El modo de lectura elimina el salto de línea final antes de escribir.
  2. El primer manejador pasa automáticamente a añadir al final.
  3. La apertura para escritura vacía el archivo antes de empezar a leer.
  4. El manejador de escritura copia cada línea antes de sustituirla.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 3 de 10

p.exists() devuelve True, pero el archivo se elimina antes de open(p, encoding="utf-8"). ¿Qué sigue necesitando un programa robusto en esa apertura?
  1. Un manejador de archivo ausente con una respuesta útil.
  2. Otra comprobación de existencia que garantice el acceso.
  3. El modo de escritura para recrear vacía la entrada esperada.
  4. Una operación de limpieza que elimine el nombre ausente.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 4 de 10

Un archivo de programa debe leer data/menu.txt junto a su propia ubicación, independientemente de la carpeta de inicio. ¿Qué expresión construye esa ruta en el archivo de programa?
  1. Path.cwd() / "data" / "menu.txt"
  2. Path(__file__).resolve().parent / "data" / "menu.txt"
  3. Path(__file__) / "data" / "menu.txt"
  4. Path("data") / "menu.txt"
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 5 de 10

Un CSV UTF-8 empieza con una marca de orden de bytes. Con encoding="utf-8", su primera clave de cabecera es "\ufeffcode". ¿Qué cambio en la apertura elimina el marcador y conserva el texto UTF-8?
  1. Usar encoding="utf-8-sig" para el archivo.
  2. Usar newline="\n" en lugar de newline="".
  3. Usar delimiter=";" en lugar de una coma.
  4. Usar skipinitialspace=True para todos los campos.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 6 de 10

Una fila es {"title": "Map", "stock": "4", "cost": "3.50"}. Un DictWriter predeterminado tiene fieldnames=["title", "stock"]. ¿Qué ocurre cuando escribe la fila completa sin cambios?
  1. Escribe dos campos y descarta cost.
  2. Añade cost a la cabecera automáticamente.
  3. Lanza ValueError por la clave adicional.
  4. Escribe cost como tercer campo sin nombre.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 7 de 10

Un bucle de entrada captura ValueError de int(text). Ese manejador imprime missing_name, que nunca se ha definido. ¿Qué ocurre con el nuevo NameError?
  1. El mismo except ValueError lo reintenta automáticamente.
  2. Se convierte en el error de conversión original.
  3. El manejador lo suprime y termina normalmente.
  4. Se propaga salvo que un manejador externo lo capture.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 8 de 10

Después de una cabecera, un registro CSV empieza con "North en la línea física 2 y termina con Hall",7 en la línea 3. Después de leerlo, ¿qué ubicación indica reader.line_num?
  1. 1
  2. 3
  3. 2
  4. 7
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 9 de 10

Una función auxiliar imprime «bad size» y devuelve None para un tamaño negativo. El código que la llama multiplica inmediatamente el resultado por 4. ¿Por qué mejoraría esta ruta de fallo lanzar ValueError durante la validación?
  1. Devuelve un valor numérico predeterminado para cálculos posteriores.
  2. Garantiza que el código que la llama reintente la solicitud.
  3. Señala el tamaño no válido antes de que fallen cálculos posteriores.
  4. Informa de un error de conversión de tipos antes de validar.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 10 de 10

Después de capturar un KeyError como err, un manejador ejecuta raise ValueError("missing unit column") from err. ¿Qué recibe el código que realiza la llamada y qué causa se conserva?
  1. Un KeyError causado por el ValueError.
  2. Un ValueError causado por el KeyError.
  3. Un ValueError sin una causa anterior.
  4. Un retorno normal con ambas cadenas de mensajes.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Set 5: Combinación del procesamiento de archivos con un manejo fiable de errores10 Preguntas de Práctica

Guarda esta unidad para ver todas las respuestas y practicar cada set.

Pregunta 1 de 10

Un programa entra en with open("source.txt", encoding="utf-8") as src, open("new.txt", "x", encoding="utf-8") as dst:. El origen se abre, pero new.txt existe. ¿Qué ocurre con src y el cuerpo?
  1. src se cierra; FileExistsError impide ejecutar el cuerpo.
  2. src sigue abierto; el cuerpo se ejecuta sin destino.
  3. src se cierra; el cuerpo añade contenido al destino.
  4. src sigue abierto; el cuerpo sustituye el destino.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 2 de 10

Un registro de actividad tiene "10:00 INFO ERROR resolved", "10:01 ERROR Disk slow" y "10:02 ERROR Disk full". El segundo campo es el nivel. Después de filtrar por nivel de error, ¿cuántos registros se guardan?
  1. 1
  2. 0
  3. 3
  4. 2
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 3 de 10

Un proceso se inicia en /srv/course, ejecuta tools/read.py y abre "../shared/items.txt". ¿Qué ruta solicita?
  1. /srv/course/shared/items.txt
  2. /srv/shared/items.txt
  3. /srv/course/tools/shared/items.txt
  4. /shared/items.txt
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 4 de 10

Un escritor CSV predeterminado recibe ["Vale, East", None, 3]. ¿Qué registro se produce, sin contar su terminador de línea final?
  1. Vale, East,None,3
  2. "Vale, East",,3
  3. "Vale, East",None,3
  4. Vale,East,,3
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 5 de 10

Un archivo de programa divide 30 entre el número 5 escrito directamente en el código, cuando el conteo previsto es 6. Imprime 6.0 sin ninguna excepción. ¿Qué clase de problema es?
  1. Un error de sintaxis causado por el divisor.
  2. Un TypeError en la división numérica.
  3. Un error lógico en el conteo elegido.
  4. Un ZeroDivisionError en el total.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 6 de 10

¿Qué se imprime antes de que se propague el error?

try:
    n = int("2")
except ValueError:
    print("bad input")
else:
    print("ready")
    result = 9 / 0
finally:
    print("cleanup")
  1. «bad input», después «cleanup»
  2. Solo «ready»
  3. Solo «cleanup»
  4. «ready», después «cleanup»
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 7 de 10

Un analizador debe aceptar todas las cadenas que acepta int(), incluidos espacios iniciales y un signo. ¿Por qué intentar int(text) en try en lugar de exigir primero text.isdigit()?
  1. Las operaciones aceptan conjuntos de cadenas distintos.
  2. isdigit() convierte cadenas con signo en números enteros.
  3. int() acepta cualquier cadena que contenga un dígito.
  4. Una sentencia try elimina los espacios de la entrada.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 8 de 10

Una herramienta ejecuta sys.exit("Required file unavailable") dentro de código cubierto por except Exception:. ¿Qué ocurre?
  1. El manejador recibe ValueError y vuelve a intentarlo.
  2. La herramienta devuelve el mensaje como un valor normal.
  3. SystemExit pasa de largo; el código de salida es 1.
  4. El manejador recibe SystemExit y continúa.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 9 de 10

Un resumen CSV inicializa total = 0 y skipped = 0. Un manejador interno salta una fila si tiene menos de dos campos o si falla int(row[1]). Añade al total los valores convertidos válidos. Para las filas ["lamp", "8"], ["desk"], ["chair", "bad"] y ["shelf", "5"], ¿qué pareja final se comunica?
  1. total = 8, skipped = 1
  2. total = 13, skipped = 2
  3. total = 13, skipped = 1
  4. total = 8, skipped = 2
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 10 de 10

Dado class ImportDataError(Exception): pass, el código que realiza la llamada captura solo ValueError. ¿Qué ocurre cuando su función auxiliar lanza ImportDataError?
  1. Se propaga porque su clase está fuera de la rama de ValueError.
  2. Se captura porque ValueError también desciende de Exception.
  3. Se captura si su mensaje describe un valor no aceptable.
  4. Se convierte en ValueError cuando la función auxiliar lo propaga.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

¿Te atascas con una pregunta tuya? Ayuda con Tareas

Términos Clave

83 Términos Clave, cada uno con su definición

A

Acumulador
Un acumulador es una variable que se actualiza durante un bucle para construir un resultado, como un total o un conteo, a partir de los registros procesados.
La variable errors empieza en 0 y aumenta en 1 cada vez que el bucle encuentra un registro de nivel de error.
Archivo cerrado
Un archivo cerrado es un objeto de archivo cuyo acceso al archivo subyacente ha terminado, por lo que ya no permite leer ni escribir a través de él.
Después de que termine el bloque, f.closed es True y f.read() lanza un ValueError sobre el acceso a un archivo cerrado.
Archivo de texto
Un archivo de texto almacena caracteres como bytes codificados, normalmente organizados en líneas, y conserva sus datos después de que termine el programa que los escribió.
Un programa lee una lista de puntuaciones guardada en un archivo de texto al empezar la siguiente ejecución.
AttributeError
Un AttributeError señala la solicitud de un atributo o método que un objeto no proporciona.
Llamar a "hi".push("!") provoca AttributeError porque una cadena de Python no tiene ningún método llamado push.

B

Bloque try
Un bloque try contiene operaciones cuyas excepciones pueden manejar las cláusulas asociadas a él, y su código restante se omite si se produce un fallo.
Una conversión de entrada va en un bloque try pequeño para que un valor incorrecto pueda provocar la solicitud de otra entrada.

C

Cabecera
Una cabecera es una fila de nombres de columnas que identifica los campos de una tabla y suele situarse antes de los registros de datos de un archivo CSV.
La fila product,stock,price da nombre a las columnas y no debe pasarse como datos a una conversión a entero.
Cadena sin procesar
Una cadena sin procesar usa un prefijo r para conservar las barras invertidas como caracteres literales en lugar de interpretarlas como secuencias de escape normales.
El literal r"C:\new\table.txt" conserva los separadores que, de otro modo, iniciarían secuencias de escape de salto de línea y tabulación.
Campo
Un campo es una parte con significado de un registro, separada o identificada por un formato conocido, como un nivel de registro de actividad o una cantidad CSV.
En un registro de actividad con fecha, hora, nivel y mensaje, comprobar el nivel evita encontrar una palabra dentro del mensaje.
Campo adicional
Un campo adicional es un valor de un registro que supera el número de campos de la cabecera; un DictReader predeterminado agrupa esos valores bajo la clave None.
Con dos nombres de cabecera, una fila de tres valores conserva los valores con nombre y almacena el valor adicional en una lista.
Campo ausente
Un campo ausente es un valor que falta en un registro CSV incompleto; un DictReader predeterminado rellena su clave de cabecera conocida con None.
Bajo name,score, la fila Ana tiene una puntuación ausente; en cambio, Ana, contiene una cadena de puntuación vacía.
Carácter de salto de línea
Un carácter de salto de línea, escrito como "\n" en una cadena de Python, marca un cambio de línea; la última línea de un archivo puede no tener terminador de línea.
Imprimir una línea que ya termina en "\n" añade otro salto de línea, salvo que se cambie el terminador de la impresión.
Clase base de excepción
Una clase base de excepción es la clase de la que deriva otra clase de error, lo que hace que sus manejadores coincidan con instancias de ese tipo derivado.
Derivar LimitError de ValueError permite que un manejador de ValueError existente también lo capture.
Cláusula else
Una cláusula else de una sentencia try se ejecuta cuando el cuerpo protegido termina normalmente, sin excepción ni salida anticipada del flujo de control.
Una conversión correcta puede dar paso a una salida en else, mientras que un error lanzado en esa salida no es capturado por los manejadores anteriores.
Cláusula finally
Una cláusula finally libera recursos cuando el control sale de una sentencia try, incluso antes de completar un retorno pendiente o de que siga propagándose una excepción no manejada.
Un mensaje de cierre en finally se imprime incluso cuando falla una conversión y ningún manejador asociado coincide con su tipo.
Codificación
Una codificación es un conjunto de reglas para representar caracteres como bytes, que se usa al escribir texto y al interpretar texto almacenado.
El texto «café» puede volverse ilegible si un lector usa una codificación distinta de la utilizada para guardarlo.
Código de salida
Un código de salida es un resultado numérico enviado al sistema operativo cuando termina un programa, que permite a otro programa detectar un fallo.
sys.exit("Missing input") imprime el mensaje en la salida de errores y termina con el código de salida 1.
Código que realiza la llamada
El código que realiza la llamada invoca una función y recibe el resultado que devuelve o una excepción que la función deja sin manejar.
El código que realiza la llamada puede capturar una retirada no válida y pedir un importe menor sin modificar la función auxiliar de cálculo.
Creación de directorios
La creación de directorios crea carpetas en el sistema de archivos; mkdir(parents=True) también puede crear las carpetas que falten por encima de la solicitada.
Crea output/daily antes de escribir su informe, ya que abrir un archivo de salida nuevo no crea carpetas.
Creación exclusiva
La creación exclusiva crea un archivo nuevo solo cuando la ruta no está ocupada y lanza FileExistsError si ya existe un archivo allí.
El modo "x" impide que un informe recién generado sustituya silenciosamente a otro situado en la misma ruta.
CSV
CSV es un formato de texto para registros de tablas formados por campos separados, con reglas de entrecomillado que permiten separadores y saltos de línea en los valores.
El registro "Lopez, Maria",10,8 tiene tres campos porque su primera coma está dentro de un nombre entrecomillado.

D

Delimitador
Un delimitador es el carácter que separa los campos en un formato de tabla, como una coma, un punto y coma o una tabulación elegidos para un lector CSV.
Una exportación con punto y coma necesita delimiter=";" para que un lector separe name;score en dos campos.
DictReader
Un DictReader lee registros de datos CSV como diccionarios cuyas claves proceden de la cabecera, mientras que los valores de los campos siguen siendo cadenas de forma predeterminada.
Después de la cabecera name,score, puede accederse a una fila con row["score"] aunque se reordenen las columnas.
DictWriter
Un DictWriter escribe diccionarios como filas CSV usando una secuencia de nombres de campos proporcionada para elegir las columnas y su orden.
Un escritor con fieldnames=["product", "stock"] exporta esas columnas cuando recibe diccionarios coincidentes.
Directorio de trabajo actual
El directorio de trabajo actual es la carpeta actual del proceso, que se usa como ubicación de partida cuando Python interpreta rutas relativas.
Ejecutar python tools/report.py desde la raíz del proyecto no cambia por sí solo el directorio a la carpeta de herramientas.
Directorio padre
Un directorio padre es la carpeta que contiene un archivo o directorio; la propiedad parent de una ruta selecciona esa ubicación contenedora.
Para Path("reports/2026/sales.csv"), el directorio padre es la ruta reports/2026.

E

Eliminación de espacios en blanco en los extremos
La eliminación de espacios en blanco en los extremos quita del principio o del final del texto caracteres de espaciado, incluidos espacios, tabulaciones y terminadores de línea.
Después de line.strip(), una línea que contiene solo espacios y un salto de línea se convierte en una cadena vacía.
Encadenamiento de excepciones
El encadenamiento de excepciones registra un error anterior como causa directa de una nueva excepción mediante raise ... from err.
Una clave de precio ausente puede convertirse en un error de fila más claro mientras la traza conserva el KeyError original como su causa.
Entrecomillado
El entrecomillado rodea un campo con comillas para que un delimitador o salto de línea dentro de su valor se conserve como parte de ese campo.
El lector conserva la coma dentro de "River, West", mientras que una simple división por comas separaría ese nombre.
Error lógico
Un error lógico hace que un programa produzca un resultado incorrecto por razonamientos u operaciones incorrectos, sin que sea necesaria una excepción.
Dividir entre un conteo incorrecto distinto de cero puede producir una media aparentemente válida mientras el programa se ejecuta hasta el final.
Escritor CSV
Un escritor CSV convierte secuencias de valores de campos en registros, transformando los valores en texto y aplicando las reglas de entrecomillado seleccionadas.
Un escritor entrecomilla automáticamente un nombre de producto que contiene una coma cuando el programa lo proporciona como un solo campo.
Excepción
Una excepción es un objeto que señala un fallo e interrumpe la ejecución normal mientras Python busca un manejador coincidente.
Una conversión fallida con int("many") lanza una excepción antes de que se ejecute la siguiente sentencia de ese bloque.
Excepción personalizada
Una excepción personalizada es una clase de error definida por el programa que permite al código que realiza las llamadas reconocer un problema concreto por separado de otros fallos.
Un InsufficientFundsError puede provocar una solicitud de un importe menor, mientras que otros valores no válidos reciben otra respuesta.
Extensión
Una extensión es el sufijo final de un nombre de archivo, incluido el punto inicial, y está disponible mediante la propiedad suffix de una ruta.
La extensión de Path("data/sales.csv") es ".csv", que un programa puede usar al seleccionar archivos de tablas.

F

Fallo controlado
Un fallo controlado es una respuesta controlada a un problema que proporciona información útil y continúa o se detiene según la tarea.
Un archivo de informe ausente provoca una solicitud clara de una ruta corregida en lugar de un cierre por error que confunda al usuario.
fieldnames
La secuencia fieldnames proporciona los nombres de cabecera leídos por un DictReader o las claves de salida esperadas y el orden proporcionados a un DictWriter.
Llamar a writeheader() en un DictWriter imprime los nombres en el orden configurado en fieldnames.
FileExistsError
Un FileExistsError señala una operación que requiere una ruta libre cuando ya existe algo en esa ubicación.
Abrir un informe existente con el modo "x" provoca FileExistsError en lugar de sustituir su contenido.
FileNotFoundError
Un FileNotFoundError señala que no se encuentra un archivo o directorio solicitado en la ruta usada por una operación del sistema de archivos.
Una carpeta de inicio incorrecta puede hacer que una ruta relativa de entrada provoque FileNotFoundError aunque el archivo exista en otro lugar.
Filtro de líneas
Un filtro de líneas selecciona registros mediante una condición al leer un archivo, permitiendo que el programa conserve solo las líneas relevantes para una tarea.
Un filtro de un registro de actividad comprueba el campo de nivel y escribe solo los registros cuyo nivel es igual a "ERROR".

G

Gestor de contexto
Un gestor de contexto es un objeto que organiza el comportamiento de entrada y salida de un bloque with, como habilitar el acceso y liberar recursos.
Un objeto de archivo actúa como gestor de contexto para que el programa pueda contar con el cierre automático al salir del bloque.

I

IndexError
Un IndexError señala una consulta a una secuencia en una posición que no existe, como acceder por índice más allá del final de una lista.
Una fila CSV incompleta con un campo provoca IndexError cuando el código basado en posiciones intenta acceder a su segundo campo.
IsADirectoryError
Un IsADirectoryError señala una operación que espera un archivo, pero encuentra un directorio en la ubicación solicitada.
En los sistemas que distinguen este caso, abrir una carpeta como un archivo de entrada normal provoca IsADirectoryError.

J

Jerarquía de excepciones
Una jerarquía de excepciones es la estructura de clases base y derivadas de los errores que determina cómo coinciden los manejadores de tipos más amplios.
Un manejador de OSError también coincide con FileNotFoundError, mientras que un manejador de ValueError no coincide con KeyError.

K

KeyboardInterrupt
Un KeyboardInterrupt señala una interrupción del usuario, normalmente Ctrl+C, y depende directamente de BaseException en lugar de Exception.
Un except: sin tipo puede capturar Ctrl+C, mientras que except Exception: permite que la interrupción se propague.
KeyError
Un KeyError señala una consulta a un diccionario con una clave ausente, incluido un nombre de cabecera CSV que no coincide con la clave solicitada.
Consultar row["name"] falla cuando la cabecera de la tabla creó en su lugar la clave "Name".

M

Manejador de excepciones
Un manejador de excepciones es un bloque except seleccionado por un tipo de excepción coincidente para dar una respuesta controlada a una operación fallida.
Un manejador de ValueError puede explicar que una cantidad debe ser un número entero y dejar que un bucle externo vuelva a preguntar.
Manejador específico
Un manejador específico captura una clase de excepción concreta, permitiendo dar mensajes distintos a los problemas esperados sin ocultar todos los errores de programación.
Sitúa FileNotFoundError antes de OSError cuando un archivo ausente necesite una respuesta distinta de la de otros problemas de archivo.
Manejo delegado de excepciones
El manejo delegado de excepciones deja una excepción al código que realizó la llamada y que dispone del contexto necesario para elegir una acción de recuperación útil para la tarea general.
Una función auxiliar de datos informa del fallo, mientras que la parte de línea de comandos decide si vuelve a intentarlo, salta un archivo o se detiene.
Marca de orden de bytes
Una marca de orden de bytes es un marcador inicial de codificación que incluyen algunas exportaciones UTF-8 y que puede aparecer en el primer campo si se conserva.
Leer con encoding="utf-8-sig" elimina el marcador inicial para que la primera cabecera coincida con el nombre previsto.
Memoria intermedia
Una memoria intermedia es una zona temporal de memoria que mantiene datos durante la entrada o salida, como texto escrito que espera llegar a un archivo.
Cerrar un archivo de salida vuelca el texto de su memoria intermedia para que las escrituras pendientes se pasen al archivo.
Mensaje de error
Un mensaje de error describe una operación fallida o un valor rechazado para que quien lo lea pueda comprender qué ocurrió y qué debe corregir.
El mensaje «el número de páginas debe ser positivo, se recibió -2» es más útil que la palabra «error» por sí sola.
Modo binario
El modo binario lee y escribe bytes sin procesar en lugar de cadenas descodificadas y, por tanto, no acepta un argumento de codificación de texto.
Un modo como "rb" identifica la entrada de bytes, mientras que los ejemplos de texto usan un modo como "r".
Modo de adición al final
El modo de adición al final abre un archivo para añadir la salida nueva al final y conservar el contenido existente; crea el archivo si no existe.
Usar "a" para mensajes de ejecución conserva las ejecuciones anteriores, pero el mensaje sigue necesitando su propio salto de línea.
Modo de apertura de archivo
Un modo de apertura de archivo es un argumento de open() que selecciona el acceso permitido y cómo trata la apertura el contenido existente en la ruta.
Un registro de actividad usa "a" para conservar mensajes anteriores, mientras que un informe nuevo puede usar "w" para sustituirlos.

N

NameError
Un NameError señala el uso de un nombre que no tiene ninguna vinculación disponible, a menudo porque se escribió mal o nunca se le asignó un valor.
Un manejador que imprime una variable no definida provoca NameError al intentar informar del problema original.
Nombre sin la última extensión
El nombre sin la última extensión es el componente final de una ruta al que se le ha quitado su último sufijo, útil para derivar nombres de salida relacionados a partir de un nombre de archivo.
Para Path("logs/run.txt"), el nombre sin la última extensión es "run", mientras que el nombre final completo es "run.txt".
Número de línea física
Un número de línea física cuenta las líneas reales del archivo, que pueden diferir del conteo de registros CSV cuando un campo entrecomillado contiene un salto de línea.
El atributo line_num del lector identifica la última línea consumida para un registro que abarca dos líneas.

O

Objeto de archivo
Un objeto de archivo es el objeto devuelto por open() que proporciona al programa métodos para leer o escribir en un archivo abierto.
Dentro de with open("notes.txt", encoding="utf-8") as f:, el nombre f hace referencia al objeto de archivo.
Objeto Path
Un objeto Path representa una ruta en Python y proporciona operaciones para unir componentes, examinar nombres y acceder al sistema de archivos.
La expresión Path("data") / "scores.txt" construye una ubicación que open() puede aceptar directamente.

P

Patrón de rutas con comodines (glob)
Un patrón de rutas con comodines selecciona rutas según un patrón de nombre, con un comodín como * que coincide con texto variable dentro del directorio seleccionado.
Path("logs").glob("*.txt") encuentra rutas de archivos de texto coincidentes; ordenarlas proporciona un orden de procesamiento predecible.
PermissionError
Un PermissionError señala que el sistema operativo deniega el acceso solicitado por una operación del sistema de archivos.
Un archivo de entrada puede existir y aun así provocar PermissionError cuando el programa no tiene permiso para leerlo.
Posición en el archivo
Una posición en el archivo marca dónde empieza la siguiente operación de lectura y avanza a medida que el programa consume texto del archivo.
Después de que f.read() haya consumido el contenido restante, una segunda lectura devuelve una cadena vacía.
Propagación
La propagación lleva una excepción no manejada hacia fuera a través de las funciones que realizan las llamadas hasta encontrar un manejador coincidente o terminar la ejecución.
Una función auxiliar de lectura de archivos puede dejar que FileNotFoundError llegue al código que la llamó y sabe si debe solicitar otra ruta.

R

Recuperación por registro
La recuperación por registro maneja un fallo esperado de un registro dentro del bucle de procesamiento, lo que permite considerar registros posteriores cuando esté permitido.
Un resumen rápido informa de una cantidad incorrecta e incrementa un conteo de omisiones antes de leer el siguiente registro CSV.
Registro
Un registro es una fila completa de campos CSV; normalmente ocupa una línea física, pero puede abarcar varias mediante un campo entrecomillado.
Una dirección entrecomillada que contiene un salto de línea sigue siendo un solo registro cuando la lee el módulo CSV.
Relanzamiento de excepciones
El relanzamiento de excepciones propaga la excepción activa capturada mediante un raise sin argumentos, permitiendo una acción local sin tratar el fallo como resuelto.
Un lector imprime la ruta ausente y después vuelve a lanzar la excepción para que el código que lo llamó decida si solicita otro archivo.
Ruta
Una ruta describe la ubicación de un archivo o carpeta mediante sus nombres y separadores, partiendo de una raíz o de otro directorio conocido.
La ruta data/notes.txt designa un archivo de texto dentro de la carpeta de datos situada bajo el directorio de trabajo actual.
Ruta absoluta
Una ruta absoluta especifica una ubicación desde la raíz de un sistema de archivos, como / en sistemas de tipo Unix o la raíz de una unidad en Windows.
La ubicación /Users/maya/data/notes.txt no depende del directorio de trabajo actual.
Ruta relativa
Una ruta relativa especifica una ubicación desde el directorio de trabajo actual del proceso, por lo que su significado depende de esa carpeta de partida.
Iniciar en project/scripts hace que ../data/notes.txt apunte a la carpeta de datos vecina del proyecto.

S

Sentencia raise
Una sentencia raise señala explícitamente una excepción, interrumpe la ruta normal e inicia la búsqueda de un manejador coincidente.
Una función rechaza un importe no positivo con raise ValueError("amount must be positive") antes de calcular.
Sentencia with
Una sentencia with entra en un bloque gestionado y organiza la liberación de recursos cuando el control sale de él; en un archivo abierto, esa liberación cierra el archivo.
Un archivo abierto en un bloque with se cierra incluso cuando convertir una línea dentro del bloque provoca un error.
SystemExit
Un SystemExit señala una salida intencionada del proceso y lo lanza sys.exit() fuera de la rama ordinaria de Exception.
Llamar a sys.exit("Missing data") lanza SystemExit con un mensaje y un código de fallo que un manejador ordinario de Exception no captura.

T

Terminador de registro
Un terminador de registro es la secuencia de caracteres que un escritor CSV añade después de una fila; el escritor predeterminado usa "\r\n".
Abrir con newline="" permite que el escritor proporcione sus propios terminadores sin una segunda capa de conversión.
Traza de la excepción
Una traza de la excepción muestra la cadena de llamadas que lleva a una excepción no manejada y termina con el tipo de excepción y un mensaje explicativo.
La entrada de llamada inferior puede identificar la división entre la longitud de una lista vacía como la operación que falló.
Truncamiento
El truncamiento vacía el contenido de un archivo existente al abrirlo en modo de escritura, antes de que el programa proporcione texto nuevo.
Abrir un archivo de entrada con "w" destruye los registros anteriores aunque el programa nunca llegue a una llamada de escritura.
TypeError
Un TypeError señala una operación aplicada a una clase de objeto inadecuada o a una combinación incompatible de tipos de objetos.
Sumar "5" y 3 provoca TypeError porque la suma de cadenas no acepta un número entero como segundo operando.

U

UnicodeDecodeError
Un UnicodeDecodeError señala que los bytes almacenados no pueden descodificarse con las reglas seleccionadas para interpretar el texto.
Un lector de texto puede provocar UnicodeDecodeError cuando la codificación real del archivo no corresponde a encoding="utf-8".
UTF-8
UTF-8 es una codificación de texto que puede representar cualquier carácter Unicode y usa un número variable de bytes por carácter.
Usa encoding="utf-8" al abrir un archivo de texto guardado como UTF-8 para que sus letras acentuadas se descodifiquen correctamente.

V

Validación
La validación comprueba si los datos de entrada cumplen los requisitos de una operación antes de que el programa los use para producir un resultado.
Una función de retirada comprueba que el importe sea positivo y no supere el saldo antes de restar.
ValueError
Un ValueError señala que una operación recibió una clase de objeto permitida, pero un valor que no puede interpretar o aceptar para esa tarea.
La cadena "3.5" es un tipo de entrada permitido para int(), pero no representa un entero y provoca ValueError.
Vinculación de una excepción a un nombre
La vinculación de una excepción a un nombre da un nombre a un objeto de error capturado mediante as para poder examinar su tipo o mensaje dentro de ese manejador.
En except ValueError as err:, imprimir err muestra el mensaje; la vinculación se elimina después.

W

writerow
El método writerow escribe una secuencia de valores de campos como un registro CSV, incluidos los separadores, las comillas y el terminador de registro necesarios.
Usa writer.writerow(["Ana", 8.5]) para un registro de dos campos, no una cadena ya unida.
writerows
El método writerows escribe una secuencia de filas y trata cada fila proporcionada como una secuencia de campos de un registro CSV.
Una lista de listas con nombres y puntuaciones puede pasarse a writerows() para guardar varios registros en una sola llamada.

Z

ZeroDivisionError
Un ZeroDivisionError señala una división o una operación aritmética relacionada con un divisor cero, lo que impide obtener un resultado numérico.
Un cálculo de media provoca ZeroDivisionError si la lista está vacía y se usa su longitud como divisor.

Sobre esta unidad

Por StudeliInformar de un error

Crea tus propios Materiales de Estudio

Convierte tus notas, diapositivas y documentos en Guías de Estudio, Preguntas de Práctica, Flashcards y 6 herramientas más.

Comenzar