Leer archivos en Python – Guía completa
Aprende todas las formas de leer archivos en Python: read(), readline(), readlines(), iteración de líneas, modo binario, codificación y pathlib.
Leer archivos es una de las tareas más comunes en Python, ya sea para cargar configuraciones, procesar registros, importar datos CSV o leer recursos binarios. Este capítulo cubre todos los métodos que Python ofrece para leer el contenido de archivos: desde la llamada más simple read() hasta la iteración línea por línea eficiente en memoria, el modo binario, el manejo de codificaciones, el control de la posición en el archivo y la API moderna pathlib.
Abrir un archivo para lectura
Toda operación con archivos comienza con la función incorporada open(). Para abrir un archivo en modo lectura, usa la cadena de modo "r" (que es el valor predeterminado cuando no se especifica ningún modo):
file_object = open("notes.txt", "r", encoding="utf-8")"r"— abre para lectura; lanzaFileNotFoundErrorsi el archivo no existe.encoding="utf-8"— especifica siempre la codificación de caracteres para archivos de texto, de modo que tu código funcione de manera idéntica en Windows, macOS y Linux.
Utiliza siempre un bloque with
La forma más segura de abrir un archivo es dentro de una sentencia with. Python cierra el archivo automáticamente cuando el bloque termina, incluso si ocurre una excepción, lo que evita fugas de recursos y garantiza que los datos en búfer se vacíen.
with open("notes.txt", "r", encoding="utf-8") as f:
contents = f.read()
# File is automatically closed hereLlamar a open() fuera de un bloque with y olvidarse de file.close() es una fuente frecuente de errores de "demasiados archivos abiertos" en scripts de larga ejecución.
Leer el archivo completo con read()
read() devuelve el contenido completo del archivo como una sola cadena.
Leer un archivo completo de una vez
with open("notes.txt", "r", encoding="utf-8") as f:
contents = f.read()
print(contents)Usa read() cuando:
- El archivo es lo suficientemente pequeño como para caber cómodamente en memoria.
- Necesitas el texto completo como una sola cadena (por ejemplo, para analizar o buscar).
Para archivos que podrían ser grandes (registros, volcados de datos), prefiere los enfoques línea por línea que se describen a continuación.
Leer un número fijo de caracteres
Pasa un entero n a read(n) para leer como máximo n caracteres desde la posición actual. Las llamadas posteriores a read(n) continúan desde donde terminó la última lectura.
Leer los primeros 50 caracteres
with open("notes.txt", "r", encoding="utf-8") as f:
first_chunk = f.read(50)
second_chunk = f.read(50)
print(repr(first_chunk))
print(repr(second_chunk))Este enfoque por fragmentos es útil cuando quieres previsualizar un archivo o procesarlo en piezas de tamaño fijo sin cargar todo en memoria.
Leer una línea a la vez con readline()
readline() lee una línea del archivo, incluido el carácter de nueva línea \n al final. Devuelve una cadena vacía "" cuando se alcanza el final del archivo, lo que facilita iterar hasta EOF.
Leer un archivo línea por línea con readline()
with open("notes.txt", "r", encoding="utf-8") as f:
line = f.readline()
while line:
print(line, end="") # line already contains '\n'
line = f.readline()El argumento end="" en print() evita que aparezca una doble nueva línea (una de la línea del archivo y otra del valor predeterminado de print).
readline() es útil cuando necesitas procesar una línea de encabezado de forma diferente al resto, o cuando quieres dejar de leer a mitad del archivo según una condición.
Iterar sobre las líneas (la forma más Pythónica)
Iterar directamente sobre un objeto de archivo es la forma más idiomática y eficiente en memoria de procesar un archivo de texto línea por línea. Python lee una línea a la vez sin cargar el archivo completo en memoria.
Iterar sobre las líneas con un bucle for
with open("notes.txt", "r", encoding="utf-8") as f:
for line in f:
print(line, end="")Este patrón es preferible a read() + split("\n") y a llamar a readline() en un bucle while, ya que es más corto y maneja correctamente todos los casos especiales (incluidos los archivos que no terminan con una nueva línea).
Buscar un patrón mientras se itera
with open("server.log", "r", encoding="utf-8") as f:
for line in f:
if "ERROR" in line:
print(line, end="")Leer todas las líneas en una lista con readlines()
readlines() devuelve una lista donde cada elemento es una línea del archivo (con el carácter de nueva línea incluido). Esto carga el archivo completo en memoria.
Leer todas las líneas en una lista
with open("notes.txt", "r", encoding="utf-8") as f:
lines = f.readlines()
print(lines[0]) # first line
print(lines[-1]) # last line
print(len(lines)) # total number of linesUsa readlines() cuando necesites acceso aleatorio a líneas específicas por índice. Para el procesamiento secuencial de arriba a abajo, el patrón for line in f es más eficiente en memoria.
Eliminar los caracteres de nueva línea
Las líneas devueltas por readline(), readlines() y la iteración con el bucle for incluyen el \n al final. Usa .strip() o .rstrip("\n") para eliminarlo:
with open("notes.txt", "r", encoding="utf-8") as f:
lines = [line.rstrip("\n") for line in f]
print(lines) # ['Line one', 'Line two', 'Line three']Elegir el método de lectura adecuado
| Método | Devuelve | ¿Carga el archivo completo? | Ideal para |
|---|---|---|---|
f.read() | str | Sí | Archivos pequeños, análisis de texto completo |
f.read(n) | str | No (por fragmentos) | Transmisión de tamaño fijo |
f.readline() | str | No | Paradas condicionales línea por línea |
for line in f | str (uno por iteración) | No | Procesamiento secuencial de líneas |
f.readlines() | list[str] | Sí | Acceso aleatorio por índice a las líneas |
Posición en el archivo: tell() y seek()
Todo objeto de archivo abierto mantiene un puntero de posición interno que avanza conforme lees. Dos métodos te permiten inspeccionarlo y controlarlo:
tell()— devuelve el desplazamiento en bytes desde el inicio del archivo.seek(offset, whence=0)— mueve el puntero. Conwhence=0(predeterminado), el desplazamiento es desde el inicio;whence=1es desde la posición actual;whence=2es desde el final.
Leer un archivo dos veces usando seek(0)
with open("notes.txt", "r", encoding="utf-8") as f:
first_pass = f.read()
print(f"Position after first read: {f.tell()}")
f.seek(0) # rewind to the beginning
second_pass = f.read()
print(first_pass == second_pass) # Trueseek() es especialmente útil en el modo "r+" (lectura y escritura), donde podrías leer una sección del archivo y luego sobrescribir una parte específica en la misma llamada a open().
Manejo de errores al leer
Un script bien escrito siempre anticipa las formas en que puede fallar la lectura de un archivo.
Manejar errores comunes de lectura
try:
with open("data.txt", "r", encoding="utf-8") as f:
content = f.read()
except FileNotFoundError:
print("Error: the file does not exist.")
except PermissionError:
print("Error: you do not have permission to read this file.")
except UnicodeDecodeError:
print("Error: the file contains bytes that are not valid UTF-8.")
except OSError as e:
print(f"OS error: {e}")Excepciones comunes que encontrarás:
| Excepción | Cuándo ocurre |
|---|---|
FileNotFoundError | La ruta no apunta a un archivo existente |
PermissionError | El proceso no tiene permiso de lectura |
IsADirectoryError | La ruta apunta a un directorio, no a un archivo |
UnicodeDecodeError | Los bytes del archivo no coinciden con la codificación especificada |
Consulta Python Try Except para obtener una guía completa sobre el manejo de excepciones.
Codificación de caracteres
Cuando Python abre un archivo en modo texto, debe saber cómo convertir los bytes en bruto en caracteres. Pasa siempre encoding= de forma explícita en lugar de depender del valor predeterminado de la plataforma, que difiere entre Windows (cp1252) y la mayoría de los sistemas Unix (utf-8).
Valores de codificación comunes:
| Codificación | Usar cuando |
|---|---|
"utf-8" | Archivos modernos, contenido web, la mayoría de proyectos Python |
"utf-8-sig" | Archivos UTF-8 creados por herramientas de Windows que anteponen un BOM |
"latin-1" | Archivos heredados de Europa Occidental |
"cp1252" | Archivos de texto ANSI de Windows |
Detectar o ignorar problemas de codificación:
Si no estás seguro de la codificación de un archivo, puedes indicarle a Python que reemplace los bytes no decodificables con un marcador de posición en lugar de lanzar un error:
with open("mystery.txt", "r", encoding="utf-8", errors="replace") as f:
content = f.read()Otros valores para errors incluyen "ignore" (omitir silenciosamente los bytes incorrectos) y "strict" (predeterminado: lanza UnicodeDecodeError).
Leer archivos binarios
Abre un archivo en modo binario añadiendo "b" a la cadena de modo ("rb"). El modo binario devuelve objetos bytes en bruto en lugar de cadenas, lo cual es correcto para imágenes, audio, archivos comprimidos, ejecutables y cualquier dato que no sea texto.
Leer un archivo binario
with open("photo.jpg", "rb") as f:
data = f.read()
print(type(data)) # <class 'bytes'>
print(len(data)) # size in bytesCopiar un archivo binario
with open("photo.jpg", "rb") as src:
data = src.read()
with open("photo_backup.jpg", "wb") as dst:
dst.write(data)No especifiques encoding en modo binario: Python lanza ValueError si lo intentas.
Leer archivos grandes de forma eficiente
Cargar un archivo de varios gigabytes con read() puede agotar la memoria del sistema. Las soluciones son:
Iteración línea por línea (archivos de texto)
with open("huge_log.txt", "r", encoding="utf-8") as f:
for line in f:
process(line) # only one line in memory at a timeFragmentos de tamaño fijo (archivos binarios)
CHUNK_SIZE = 65536 # 64 KB
with open("large_file.bin", "rb") as f:
while True:
chunk = f.read(CHUNK_SIZE)
if not chunk:
break
process(chunk)Ambos patrones mantienen el uso de memoria constante independientemente del tamaño del archivo.
Leer archivos con pathlib
Python 3.4 introdujo pathlib.Path, que proporciona una interfaz orientada a objetos para las rutas del sistema de archivos. Para lecturas y escrituras simples de una sola vez, los objetos Path son más concisos que open().
Leer texto con Path.read_text()
from pathlib import Path
content = Path("notes.txt").read_text(encoding="utf-8")
print(content)Leer bytes con Path.read_bytes()
from pathlib import Path
data = Path("photo.jpg").read_bytes()
print(len(data)) # file size in bytesread_text() y read_bytes() abren el archivo, leen su contenido completo y lo cierran en una sola llamada. Úsalos para archivos pequeños cuando solo necesitas el contenido. Usa open() con un bloque with cuando necesites iteración línea por línea, lectura por fragmentos, seek() o cualquier otro control detallado.
Verificar que un archivo existe antes de leerlo
from pathlib import Path
p = Path("data.txt")
if p.exists() and p.is_file():
content = p.read_text(encoding="utf-8")
else:
print("File not found.")Nota: p.exists() puede devolver un resultado obsoleto en código multihilo. En esos casos es más seguro intentar la lectura y capturar FileNotFoundError.
Ejemplo práctico: leer un archivo de configuración simple
Muchos scripts leen un archivo de configuración en texto plano que almacena un par clave=valor por línea. Aquí tienes un ejemplo completo y funcional:
Analizar un archivo de configuración clave=valor
from pathlib import Path
def load_config(path):
config = {}
with open(path, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
if not line or line.startswith("#"):
continue # skip blank lines and comments
key, _, value = line.partition("=")
config[key.strip()] = value.strip()
return config
# Example config.txt contents:
# host = localhost
# port = 8080
# debug = true
config = load_config("config.txt")
# config == {'host': 'localhost', 'port': '8080', 'debug': 'true'}str.partition("=") divide solo en el primer =, por lo que los valores que contienen = (como las cadenas en Base64) se manejan correctamente.
Capítulos relacionados
- Python File Handling — modos de apertura, sentencia
with,seek(), archivos binarios, resumen de pathlib - Python Write / Create Files — escribir, crear y añadir contenido a archivos
- Python Delete Files — eliminar archivos y directorios de forma segura
- Python Try Except — manejo de excepciones en Python
- Python CSV — leer y escribir archivos CSV con el módulo
csv