ftplib viene con Python y hace todo lo que hace un cliente de FTP. Antes de empezar, una advertencia que la versión anterior de esta página no hacía: el FTP normal envía la contraseña sin cifrar.
También te puede interesar
Conectarse
from ftplib import FTP
with FTP() as ftp:
ftp.connect("ftp.ejemplo.com", 21, timeout=10)
ftp.login("usuario", "clave")
print(ftp.getwelcome())
print("carpeta:", ftp.pwd())salida220 Servidor FTP de pruebas carpeta: /
El with cierra la conexión al salir. El timeout no es opcional en la práctica: sin él, si el servidor no responde, el programa se queda esperando indefinidamente. Los ejemplos de esta página se probaron contra un servidor FTP de pruebas montado para la ocasión, y las salidas son las suyas.
Carpetas
| Para… | Usa |
|---|---|
| Ver dónde estás | ftp.pwd() |
| Entrar en una carpeta | ftp.cwd("informes") |
| Subir un nivel | ftp.cwd("..") |
| Crear una carpeta | ftp.mkd("informes") |
| Borrar una carpeta vacía | ftp.rmd("informes") |
| Listar nombres | ftp.nlst() |
Subir y bajar
with open("subir.txt", "rb") as f:
print(ftp.storbinary("STOR subir.txt", f))
with open("bajado.txt", "wb") as f:
ftp.retrbinary("RETR subir.txt", f.write)salida226 Transfer complete.
Fíjate en los modos: el archivo local se abre en binario, "rb" para subir y "wb" para bajar, y se usan storbinary y retrbinary. Existen las versiones de texto —storlines y retrlines—, pero cambian los saltos de línea por el camino y pueden estropear un archivo que no sea texto puro. Con binario el archivo llega idéntico, sea lo que sea.
Listar con detalle: mlsd
for nombre, datos in ftp.mlsd():
if datos["type"] == "file":
print(f" {nombre}: {datos['size']} bytes")salidasubir.txt: 13 bytes
mlsd devuelve cada entrada con sus datos ya separados —tipo, tamaño, fecha—, en lugar de una línea de texto con un formato que cambia de un servidor a otro. Los servidores muy antiguos no lo soportan; en ese caso queda ftp.dir(), y toca interpretar el texto.
Renombrar, borrar y errores
ftp.rename("subir.txt", "renombrado.txt")
ftp.delete("renombrado.txt")
ftp.cwd("no_existe")salidaerror_perm: 550 No such file or directory.
Los errores del servidor llegan como ftplib.error_perm y empiezan por el código de FTP: 550 es «no existe o no tienes permiso», 530 es «usuario o contraseña incorrectos».
La parte importante: cifrar
from ftplib import FTP_TLS
with FTP_TLS("ftp.ejemplo.com", timeout=10) as ftp:
ftp.login("usuario", "clave")
ftp.prot_p() # cifra también los datos, no solo la contraseñaFTP a secas, el usuario, la contraseña y los archivos viajan en claro, y cualquiera en el camino —una wifi pública, un equipo intermedio— puede leerlos. Si el servidor lo admite, usa FTP_TLS, que viene en la misma biblioteca, y no olvides prot_p(). Si lo que tienes es acceso por SSH, mejor todavía SFTP, que es otro protocolo distinto y se usa con el paquete paramiko.Más información en inglés: FTP client in Python.
Todo el código se ejecutó con Python 3.14 en un contenedor limpio antes de publicar esta página; las salidas están copiadas de esa ejecución.