W3docs

Escribir y Crear Archivos en Python

Aprende a escribir archivos en Python: write(), writelines(), modo append, escritura binaria, pathlib y patrones seguros con bloques with.

Escribir archivos es una de las operaciones de E/S más fundamentales en Python. Ya sea que guardes la salida de un programa, persistas configuraciones, exportes datos a CSV o registres eventos, necesitas una forma confiable de crear y actualizar archivos. Este capítulo cubre todos los enfoques que ofrece Python: write(), writelines(), modo append, escrituras binarias, manejo de saltos de línea, codificación de caracteres, la API moderna de pathlib y patrones para escribir de forma segura sin pérdida de datos.

Abrir un Archivo para Escritura

Toda operación de escritura de archivos comienza con la función integrada open(). El segundo argumento — el modo — controla lo que ocurre al abrir el archivo:

ModoSignificadoEl archivo existeEl archivo no existe
"w"Escritura (texto)Trunca (borra) el archivoCrea un nuevo archivo
"a"Append (texto)Mueve el puntero al finalCrea un nuevo archivo
"x"Creación exclusivaLanza FileExistsErrorCrea un nuevo archivo
"wb"Escritura (binaria)Trunca el archivoCrea un nuevo archivo
"ab"Append (binaria)Mueve el puntero al finalCrea un nuevo archivo
"r+"Lectura + escrituraAbre en su lugarLanza FileNotFoundError

Lo más importante a recordar sobre el modo "w": borra silenciosamente el archivo completo antes de escribir. Si solo deseas agregar contenido a un archivo existente, usa el modo "a" (append) en su lugar.

Siempre proporciona el parámetro encoding al escribir archivos de texto para que tu código se comporte de manera idéntica en Windows, macOS y Linux:

file = open("output.txt", "w", encoding="utf-8")

Usa Siempre un Bloque with

Llamar a open() sin un bloque with significa que debes llamar a file.close() tú mismo. Olvidar cerrar un archivo provoca que los datos en el buffer nunca se escriban en disco, errores de demasiados archivos abiertos en scripts de larga ejecución y corrupción de archivos en algunos sistemas operativos.

La sentencia with (un gestor de contexto) resuelve todos estos problemas. Python cierra el archivo automáticamente cuando el bloque termina — incluso si se lanza una excepción dentro del bloque.

with open("output.txt", "w", encoding="utf-8") as f:
    f.write("Hello, World!\n")
# File is closed and flushed here — guaranteed

Todos los ejemplos de este capítulo usan la sentencia with. Evita el patrón manual de open() / close().

Escribir Texto con write()

file.write(string) escribe la cadena dada en el archivo y devuelve el número de caracteres escritos. No agrega un salto de línea automáticamente — debes incluir \n tú mismo.

Escribir una sola línea en un nuevo archivo

with open("greeting.txt", "w", encoding="utf-8") as f:
    chars_written = f.write("Hello, World!\n")
    print(chars_written)   # 14

Escribir múltiples líneas llamando a write() repetidamente

with open("poem.txt", "w", encoding="utf-8") as f:
    f.write("Roses are red,\n")
    f.write("Violets are blue,\n")
    f.write("Python is great,\n")
    f.write("And so are you.\n")

Cada llamada a write() agrega contenido al archivo en la posición actual. El archivo se escribe desde cero (cualquier contenido anterior se pierde) porque se usó el modo "w".

Escribir Múltiples Líneas con writelines()

file.writelines(iterable) acepta cualquier iterable de cadenas — una lista, un generador o una tupla — y escribe cada elemento en secuencia. Al igual que write(), no agrega saltos de línea entre elementos.

Escribir una lista de líneas

lines = [
    "First line\n",
    "Second line\n",
    "Third line\n",
]

with open("lines.txt", "w", encoding="utf-8") as f:
    f.writelines(lines)

Si tus datos de origen no contienen ya \n, agrégalo antes de escribir:

data = ["Alice", "Bob", "Charlie"]

with open("names.txt", "w", encoding="utf-8") as f:
    f.writelines(name + "\n" for name in data)

La expresión generadora name + "\n" for name in data es eficiente en memoria: Python produce cada cadena a demanda en lugar de construir toda la lista en memoria primero.

write() vs writelines() — Cuándo Usar Cada Uno

write()writelines()
EntradaUna sola cadenaCualquier iterable de cadenas
Saltos de líneaTú controlas cada \nTú controlas cada \n
Mejor paraConstruir la salida incrementalmenteEscribir una secuencia pre-construida de una vez

Crear un Archivo que No Debe Existir

Usa el modo "x" (creación exclusiva) cuando deseas que Python cree un nuevo archivo y falle si el archivo ya existe. Esto evita sobrescribir accidentalmente datos importantes.

try:
    with open("config.txt", "x", encoding="utf-8") as f:
        f.write("host=localhost\n")
        f.write("port=8080\n")
except FileExistsError:
    print("config.txt already exists — not overwriting.")

Este patrón es útil para generar archivos de salida únicos (registros, exportaciones, instantáneas) donde una colisión indica que algo salió mal.

Agregar Contenido a un Archivo Existente

Abrir un archivo con el modo "a" mueve el puntero de escritura al final del archivo. El nuevo contenido se agrega después del contenido existente; nada se borra.

Agregar una entrada de registro a un archivo existente

import datetime

with open("app.log", "a", encoding="utf-8") as f:
    timestamp = datetime.datetime.now().isoformat()
    f.write(f"[{timestamp}] Server started\n")

Si app.log no existe aún, Python lo crea. Si ya existe, la nueva línea se agrega al final. Ejecutar el script varias veces construye un registro en crecimiento.

Escritura vs Append — Elegir el Modo Correcto

  • Usa "w" cuando quieras reemplazar completamente el contenido del archivo (generar un informe nuevo, guardar una nueva configuración).
  • Usa "a" cuando quieras agregar al contenido existente (registros, acumulación de resultados en múltiples ejecuciones).

Saltos de Línea y Terminaciones de Línea

El modo de texto de Python ("w", "a", "r") traduce el salto de línea universal \n a la terminación de línea nativa de la plataforma al escribir:

  • Windows: \n\r\n (CRLF)
  • macOS / Linux: \n permanece \n (LF)

Este suele ser el comportamiento correcto — los archivos escritos en Windows se abren correctamente en el Bloc de notas.

Si necesitas forzar una terminación de línea específica independientemente de la plataforma — por ejemplo, al generar archivos que deben ser leídos por un sistema específico — pasa el parámetro newline:

# Force Unix-style LF on all platforms (e.g. for Linux-target files)
with open("unix_file.txt", "w", encoding="utf-8", newline="\n") as f:
    f.write("line one\n")
    f.write("line two\n")

# Preserve line endings exactly as given (no translation at all)
with open("raw.txt", "w", encoding="utf-8", newline="") as f:
    f.write("line one\r\n")
    f.write("line two\n")

Codificación de Caracteres

Siempre especifica encoding= al escribir archivos de texto. Depender del valor predeterminado de la plataforma arriesga crear archivos que no puedan leerse en otros sistemas.

Codificaciones recomendadas para escenarios comunes:

CodificaciónUsar cuando
"utf-8"Uso general; funciona para todos los idiomas; predeterminado para la mayoría de proyectos Python
"utf-8-sig"UTF-8 con BOM — útil para archivos que se abrirán en Excel en Windows
"latin-1"Archivos heredados de Europa Occidental
"cp1252"Texto ANSI de Windows

Escribir un archivo con codificación UTF-8

with open("international.txt", "w", encoding="utf-8") as f:
    f.write("English: Hello\n")
    f.write("Japanese: こんにちは\n")
    f.write("Arabic: مرحبا\n")

Escribir Archivos Binarios

Abre un archivo con el modo "wb" (escritura binaria) para escribir bytes crudos en lugar de cadenas. El modo binario es necesario para imágenes, audio, archivos comprimidos, ejecutables y cualquier dato que no sea texto. No especifiques encoding en modo binario.

Escribir bytes en un archivo binario

data = bytes([0x89, 0x50, 0x4E, 0x47])  # PNG magic bytes

with open("header.bin", "wb") as f:
    f.write(data)
    print(f.write(b"\r\n\x1a\n"))   # 4

Copiar un archivo binario

with open("photo.jpg", "rb") as src:
    content = src.read()

with open("photo_backup.jpg", "wb") as dst:
    dst.write(content)

Para archivos binarios grandes, lee y escribe en fragmentos para evitar cargar todo el archivo en memoria:

CHUNK = 65536  # 64 KB

with open("large.bin", "rb") as src, open("large_copy.bin", "wb") as dst:
    while True:
        chunk = src.read(CHUNK)
        if not chunk:
            break
        dst.write(chunk)

Manejo de Errores al Escribir

Un script de calidad de producción siempre anticipa las formas en que puede fallar la escritura de un archivo.

Manejar errores comunes de escritura

try:
    with open("/etc/protected.txt", "w", encoding="utf-8") as f:
        f.write("data\n")
except PermissionError:
    print("Error: you do not have write permission for this file.")
except FileNotFoundError:
    print("Error: one or more directories in the path do not exist.")
except IsADirectoryError:
    print("Error: the path points to a directory, not a file.")
except OSError as e:
    print(f"OS error: {e}")

Excepciones comunes que encontrarás:

ExcepciónCuándo ocurre
PermissionErrorEl proceso carece de permiso de escritura
FileNotFoundErrorUn directorio intermedio en la ruta no existe
FileExistsErrorModo "x" y el archivo ya existe
IsADirectoryErrorLa ruta apunta a un directorio
OSErrorDisco lleno, error de sistema de archivos en red y otros problemas a nivel del sistema operativo

Consulta Python Try Except para una guía completa sobre el manejo de excepciones.

Escribir Archivos de Forma Segura (Patrón de Escritura Atómica)

Un simple open("file.txt", "w") no es seguro para datos críticos: si tu script falla o se interrumpe a mitad de la escritura, el archivo queda en un estado parcialmente escrito y corrupto. La solución estándar es una escritura atómica: escribe primero en un archivo temporal y luego renómbralo sobre el destino.

import os
import tempfile

def write_file_safely(path, content, encoding="utf-8"):
    """Write content to path atomically using a temp file + rename."""
    dir_name = os.path.dirname(os.path.abspath(path)) or "."
    # Write to a temp file in the same directory (same filesystem = atomic rename)
    fd, tmp_path = tempfile.mkstemp(dir=dir_name)
    try:
        with os.fdopen(fd, "w", encoding=encoding) as f:
            f.write(content)
        os.replace(tmp_path, path)   # atomic on POSIX; best-effort on Windows
    except Exception:
        os.unlink(tmp_path)          # clean up if something went wrong
        raise

write_file_safely("important.txt", "critical data\n")

os.replace() (Python 3.3+) reemplaza el destino atómicamente en sistemas POSIX: los lectores ven el archivo antiguo o el nuevo, nunca una escritura parcial.

Escribir Archivos con pathlib

pathlib.Path (introducido en Python 3.4) proporciona una API concisa y orientada a objetos. Para escrituras simples de una sola vez, Path.write_text() y Path.write_bytes() son más legibles que open().

Path.write_text()

from pathlib import Path

Path("output.txt").write_text("Hello from pathlib!\n", encoding="utf-8")

write_text() abre el archivo en modo "w", escribe la cadena y cierra el archivo — todo en una sola llamada. Siempre sobreescribe el archivo. No hay un equivalente de append; para agregar contenido usa open() con modo "a".

Path.write_bytes()

from pathlib import Path

Path("data.bin").write_bytes(b"\x00\x01\x02\x03")

Construir Rutas con pathlib

pathlib también facilita la construcción de rutas de forma segura sin concatenación de cadenas:

from pathlib import Path

output_dir = Path("results")
output_dir.mkdir(exist_ok=True)          # create the directory if needed

report_path = output_dir / "report.txt"
report_path.write_text("Run complete.\n", encoding="utf-8")

print(report_path)         # results/report.txt
print(report_path.exists())  # True

El operador / en objetos Path une segmentos de ruta — sin necesidad de os.path.join().

Ejemplo Práctico: Escribir un Informe CSV

El siguiente ejemplo completo escribe una lista de registros en un archivo CSV usando solo herramientas integradas (sin el módulo csv), demostrando varios conceptos de este capítulo juntos.

from pathlib import Path
import datetime

def write_csv_report(path, headers, rows):
    """Write a simple CSV file with a header row."""
    with open(path, "w", encoding="utf-8", newline="") as f:
        f.write(",".join(headers) + "\n")
        for row in rows:
            f.write(",".join(str(v) for v in row) + "\n")

records = [
    ("Alice", 30, "Engineering"),
    ("Bob", 25, "Marketing"),
    ("Charlie", 35, "Finance"),
]

output = Path("staff_report.txt")
write_csv_report(output, ["Name", "Age", "Department"], records)

print(output.read_text(encoding="utf-8"))

Salida esperada:

Name,Age,Department
Alice,30,Engineering
Bob,25,Marketing
Charlie,35,Finance

Nota que newline="" se pasa a open() para que Python no traduzca doblemente las terminaciones de línea dentro de las filas CSV — esto coincide con la recomendación en la documentación del módulo csv de Python.

Para casos más complejos (comillas, dialectos, casos extremos de Unicode) usa el módulo integrado Python CSV en su lugar.

Referencia Rápida

ObjetivoPatrón de código
Crear o sobreescribir un archivoopen("f.txt", "w", encoding="utf-8")
Agregar contenido a un archivoopen("f.txt", "a", encoding="utf-8")
Crear solo si es nuevoopen("f.txt", "x", encoding="utf-8")
Escribir datos binariosopen("f.bin", "wb")
Escribir una cadenaf.write("text\n")
Escribir una lista de cadenasf.writelines(lines)
Escritura de texto en una sola llamadaPath("f.txt").write_text("...", encoding="utf-8")
Escritura binaria en una sola llamadaPath("f.bin").write_bytes(b"...")
Escritura segura / atómicaEscribe en archivo temporal, luego os.replace()

Capítulos Relacionados

Was this page helpful?