Aprende leyendo en orden

shutil y tempfile — Operaciones masivas de archivos y archivos temporales

Aprende shutil y tempfile de Python desde cero. Operaciones masivas de archivos con shutil.copy / shutil.move / shutil.rmtree, además de cómo usar archivos temporales de forma segura vía tempfile.NamedTemporaryFile — todo práctico.

Este artículo recorre dos módulos: shutil, que opera sobre archivos y carpetas enteros, y tempfile, que maneja archivos temporales desechables. Cubrirás operaciones masivas de archivos con shutil.copy / move / rmtree, la forma segura de usar NamedTemporaryFile y el patrón de escritura atómica que combina ambos.

shutil — Operaciones de archivos y carpetas en una línea

shutil viene de shell utilities — es la biblioteca estándar que te permite llamar operaciones estilo shell como cp / mv / rm -r desde Python en una sola línea. El módulo os tiene cosas como os.rename, pero shutil añade operaciones de más alto nivel como copia recursiva de carpetas y borrado de árbol.

Tres funciones núcleo de shutil
shutil.copy(src, dst)Hacer una copiashutil.move(src, dst)Mover o renombrarshutil.rmtree(path)Borrado recursivo
copy duplica un archivo a otra ubicación, move lo mueve (o lo renombra en el sitio) y rmtree borra recursivamente una carpeta entera. Estas tres cubren la mayoría de las operaciones del día a día.
FunciónComportamientoNotas
shutil.copy(src, dst)Duplica un archivoSi dst es una carpeta, va dentro con el mismo nombre
shutil.copy2(src, dst)copy más metadatos como la hora de modificaciónBueno para copias de seguridad
shutil.copytree(src, dst)Duplica recursivamente una carpeta enteradst **no debe existir**
shutil.move(src, dst)Mueve o renombra un archivo o carpetaEquivalente a renombrar cuando src y dst comparten el mismo padre
shutil.rmtree(path)Borra recursivamente una carpeta y su contenidoNo reversible — comprueba dos veces el destino antes de ejecutar
import shutil
import os

# 1) Copiar un archivo a otra ubicación (una copia de seguridad típica)
os.makedirs("backups", exist_ok=True)        # Asegúrate de que la carpeta destino existe
shutil.copy("data/sales.csv", "backups/sales_2024.csv")

shutil.move("logs/temp.log", "logs/archive_2024.log")

shutil.rmtree("old_data")

rmtree no se puede deshacer

shutil.rmtree(path) borra físicamente todo lo que está bajo path. Python no pasa por una papelera — desaparece al instante. En un proyecto real, imprime el destino antes de borrar, añade una guarda como if path.startswith("/tmp"), y construye hábitos que te protejan a ti y a tu código.

Haz una copia de seguridad del CSV de ventas data/sales.csv como backups/sales_backup.csv. Puedes inspeccionar el original desde el panel 📂 Files a la izquierda.

① Por favor importa shutil y os.

② Por favor prepara la carpeta destino backups/ (de una forma que no dé error si ya existe).

③ Por favor copia el archivo al nombre destino anterior.

④ Por favor verifica tanto la copia de seguridad como el original imprimiendo Copia hecha: True / Origen sigue existiendo: True.

(Si lo ejecutas correctamente la explicación aparece abajo.)

Editor Python

Ejecutar el código para ver el resultado

tempfile — Crear archivos desechables de forma segura

tempfile es la biblioteca estándar para archivos temporales que se limpian automáticamente cuando terminas con ellos. La usas para guardar resultados intermedios, hacer buffer de datos grandes, mantener carpetas de trabajo de prueba — cualquier cosa que solo necesite existir mientras corre el proceso.

Si te inventas tus propios nombres como tmp_xxx.txt, te arriesgas a chocar con otros procesos u olvidarte de borrarlos. tempfile en cambio crea archivos en la carpeta temporal del SO bajo un nombre garantizado como único y los elimina automáticamente cuando el trabajo termina.

Ciclo de vida de NamedTemporaryFile
with NamedTemporaryFile():→ Archivo temp creadoDentro del bloque:escribir y leerSales del bloque→ Auto-borradoÚsalo de forma segurasin limpieza
El archivo se crea en el momento en que entras al bloque with y se borra automáticamente cuando lo dejas. El nombre se asigna sobre la marcha para evitar choques — no lo eliges tú.
Función / atributoSignificadoNotas
tempfile.NamedTemporaryFileArchivo temp que abres y cierras con `with`delete=False lo conserva tras el bloque
tempfile.mkdtemp()Devuelve la ruta de una carpeta tempLa borras tú mismo con shutil.rmtree
tempfile.gettempdir()Devuelve la ruta de la carpeta temp del SO/tmp en Linux, ruta diferente en macOS
tf.nameLa ruta de archivo real (nombre aleatorio)Accesible dentro del bloque `with`
tf.write / tf.readMisma API que un objeto de archivo normalElige 'w' / 'r' / 'w+' vía el argumento mode
import tempfile
import os

# Abre de forma segura con `with`, luego auto-borra
with tempfile.NamedTemporaryFile(mode="w+", suffix=".txt", delete=True) as tf:
    tf.write("datos de agregación intermedios\n")
    tf.seek(0)
    print("Contenido:", tf.read())
    print("Ruta:", tf.name)
# ← El bloque termina aquí y el archivo se auto-borra

Cuándo combinar delete=False con `with`

Cuando quieres escribir el archivo y leerlo de vuelta más tarde desde otro sitio, pasa delete=False para que el archivo sobreviva a la salida del bloque with. Una vez que termines con él, bórralo tú mismo con os.remove(path) o muévelo al destino real con shutil.move — ese es el patrón de escritura atómica cubierto abajo.

Crea un archivo temporal, escribe en él, luego comprueba si existe antes y después del borrado. Abre un NamedTemporaryFile con delete=False, escribe en él, léelo de vuelta, comprueba la existencia antes del borrado, bórralo y luego comprueba la existencia de nuevo.

① Por favor importa tempfile y os.

② Por favor abre un archivo temp con NamedTemporaryFile(mode="w", delete=False), escribe la cadena total de ventas: 3750, guarda tf.name en una variable de ruta y sal del bloque with.

③ Por favor imprime la existencia con os.path.exists(path) con la forma Existe antes de borrar: ◯◯.

④ Por favor borra el archivo con os.unlink(path).

⑤ Por favor imprime la existencia de nuevo con os.path.exists(path) con la forma Existe tras borrar: ◯◯.

Editor Python

Ejecutar el código para ver el resultado

Archivos temp con borrado automático con `delete=True`

Si sobrescribes un archivo de configuración o de estado importante directamente con open("settings.json", "w"), un crash del proceso a media escritura puede dejar atrás un archivo a medio escribir, que luego falla al parsear en la siguiente lectura. La forma estándar de evitar esto es el patrón "escribe a un archivo temp completamente, luego renombra / muévelo a la ruta real" — conocido como escritura atómica (atómica — incluso si se interrumpe, los observadores solo pueden ver "completada" o "no iniciada", nunca un estado intermedio).

Flujo de una escritura atómica
open directo("w")Crash a media escrituraArchivo rotoqueda atrásEscribe completoal tempfileshutil.move ala ruta realEl intercambio esinstantáneo desde fueraEstado rotonunca visible
Escribir directamente deja un archivo roto en un crash, pero pasar por un archivo temp intercambia a la ruta real solo en el momento en que la escritura está completa — así que el estado roto nunca es visible.
import tempfile
import shutil
import json

final_path = "settings.json"
new_settings = {"theme": "dark", "lang": "en", "fontSize": 14}

# 1) Escribe completo a un archivo temp
with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".json") as tf:
    json.dump(new_settings, tf)
    temp_path = tf.name

# 2) Una vez terminado, mueve a la ruta real (este único momento es el "intercambio")
shutil.move(temp_path, final_path)

# 3) Verifica
with open(final_path) as f:
    print(json.load(f))
# → {'theme': 'dark', 'lang': 'en', 'fontSize': 14}

Un objeto de archivo tiene una posición actual de lectura/escritura (cursor), y llamar a `tf.write(...)` mueve el cursor justo después de lo que se escribió (= el final). Llamar a tf.read() desde ahí devuelve una cadena vacía porque no hay nada más allá del cursor, así que el movimiento estándar es resetear el cursor al inicio con `tf.seek(0)` antes de leer.

Cómo se comportan el cursor del archivo y seek(0)
write("config: ok")Cursor → finalread()→ "" (vacío)seek(0)Cursor → inicioread()→ "config: ok"
write mueve el cursor al final → leer desde ahí devuelve una cadena vacíaseek(0) trae el cursor de vuelta al inicio → read devuelve lo que escribiste.

mode="w+" es modo lectura-escritura

`mode="w+"` es el modo que te deja escribir y leer a través del mismo handle de archivo. Con solo "w" eres write-only y read() no funciona; con solo "r" eres read-only y write() no funciona. Para ejercicios que escriben e inmediatamente leen de vuelta, "w+" es obligatorio.

Crea un archivo temp con `with NamedTemporaryFile(delete=True)` y confirma que se auto-borra. Escribe en él dentro del bloque with, léelo de vuelta y luego comprueba la existencia tras salir del bloque — debe ser False.

① Por favor importa tempfile y os.

② Por favor abre tempfile.NamedTemporaryFile(mode="w+", delete=True) con una sentencia with (mode="w+" es lectura-escritura).

③ Dentro del bloque, por favor escribe tf.write("config: ok\n"), resetea el cursor al inicio con tf.seek(0), lee de vuelta con tf.read() e imprímelo como Contenido: ◯◯.

④ Por favor guarda la ruta dentro del bloque como saved_path = tf.name.

⑤ Tras salir del bloque, por favor imprime el resultado de os.path.exists(saved_path) con la forma Existe tras with: ◯◯ (debe ser False).

Editor Python

Ejecutar el código para ver el resultado
QUIZ

Verificación de conocimientos

Responde cada pregunta una a una.

Pregunta 1¿Cuál de las siguientes usas cuando quieres borrar recursivamente una carpeta entera?

Pregunta 2¿Cuál es una razón típica para usar tempfile.NamedTemporaryFile con delete=False?

Pregunta 3¿Cuál es la esencia de la escritura atómica?