Python's ftplib module provides an FTP client for uploading, downloading, and managing files on FTP servers.
Basic Connection
from ftplib import FTP
# Connect and login
ftp = FTP('ftp.example.com')
ftp.login('username', 'password')
# Show current directory
print(ftp.pwd())
# List files
ftp.dir()
# Disconnect
ftp.quit()Secure Connection (FTPS)
from ftplib import FTP_TLS
# Implicit TLS
ftp = FTP_TLS('ftp.example.com')
ftp.login('username', 'password')
ftp.prot_p() # Switch to secure data connection
# Do work...
ftp.quit()Context Manager
from ftplib import FTP
with FTP('ftp.example.com') as ftp:
ftp.login('username', 'password')
ftp.dir()
# Automatically closes connectionDownloading Files
from ftplib import FTP
with FTP('ftp.example.com') as ftp:
ftp.login('username', 'password')
# Download binary file
with open('local_file.zip', 'wb') as f:
ftp.retrbinary('RETR remote_file.zip', f.write)
# Download text file
lines = []
ftp.retrlines('RETR readme.txt', lines.append)
content = '\n'.join(lines)Uploading Files
from ftplib import FTP
with FTP('ftp.example.com') as ftp:
ftp.login('username', 'password')
# Upload binary file
with open('local_file.zip', 'rb') as f:
ftp.storbinary('STOR remote_file.zip', f)
# Upload text file
with open('readme.txt', 'rb') as f:
ftp.storlines('STOR readme.txt', f)Directory Operations
from ftplib import FTP
with FTP('ftp.example.com') as ftp:
ftp.login('username', 'password')
# Current directory
print(ftp.pwd()) # /home/user
# Change directory
ftp.cwd('/public')
# Go up one level
ftp.cwd('..')
# Create directory
ftp.mkd('new_folder')
# Remove directory
ftp.rmd('empty_folder')File Operations
from ftplib import FTP
with FTP('ftp.example.com') as ftp:
ftp.login('username', 'password')
# Delete file
ftp.delete('old_file.txt')
# Rename file
ftp.rename('old_name.txt', 'new_name.txt')
# Get file size
size = ftp.size('file.zip')
print(f"Size: {size} bytes")
# Get modification time
mtime = ftp.sendcmd('MDTM file.txt')
print(mtime)Listing Files
from ftplib import FTP
with FTP('ftp.example.com') as ftp:
ftp.login('username', 'password')
# Detailed listing (Unix ls -l style)
ftp.dir()
# Simple list of names
files = ftp.nlst()
print(files)
# Parse detailed listing
file_list = []
ftp.dir(file_list.append)
for line in file_list:
print(line)MLSD (Modern Listing)
from ftplib import FTP
with FTP('ftp.example.com') as ftp:
ftp.login('username', 'password')
# Machine-readable listing
for name, facts in ftp.mlsd():
print(f"{name}: {facts}")
# facts = {'type': 'file', 'size': '1234', 'modify': '...'} Anonymous FTP
from ftplib import FTP
with FTP('ftp.gnu.org') as ftp:
ftp.login() # Anonymous login
ftp.cwd('/gnu')
ftp.dir()Progress Tracking
from ftplib import FTP
def download_with_progress(ftp, remote_path, local_path):
# Get file size
size = ftp.size(remote_path)
downloaded = 0
def callback(data):
nonlocal downloaded
downloaded += len(data)
percent = (downloaded / size) * 100
print(f"\rDownloading: {percent:.1f}%", end='')
return data
with open(local_path, 'wb') as f:
def write_callback(data):
f.write(callback(data))
ftp.retrbinary(f'RETR {remote_path}', write_callback)
print() # Newline
with FTP('ftp.example.com') as ftp:
ftp.login('user', 'pass')
download_with_progress(ftp, 'large_file.zip', 'local.zip')Passive Mode
from ftplib import FTP
with FTP('ftp.example.com') as ftp:
ftp.login('username', 'password')
# Enable passive mode (usually default)
ftp.set_pasv(True)
# Active mode (for servers that require it)
ftp.set_pasv(False)Timeout and Error Handling
from ftplib import FTP, error_perm, error_temp
import socket
try:
with FTP('ftp.example.com', timeout=30) as ftp:
ftp.login('username', 'password')
ftp.retrbinary('RETR file.zip', open('file.zip', 'wb').write)
except error_perm as e:
print(f"Permission error: {e}")
except error_temp as e:
print(f"Temporary error: {e}")
except socket.timeout:
print("Connection timed out")
except ConnectionRefusedError:
print("Could not connect to server")Sync Directory
from ftplib import FTP
from pathlib import Path
def upload_directory(ftp, local_dir, remote_dir):
"""Upload a local directory to FTP."""
local_path = Path(local_dir)
try:
ftp.mkd(remote_dir)
except:
pass
ftp.cwd(remote_dir)
for item in local_path.iterdir():
if item.is_file():
with open(item, 'rb') as f:
ftp.storbinary(f'STOR {item.name}', f)
print(f"Uploaded: {item.name}")
elif item.is_dir():
upload_directory(ftp, item, item.name)
ftp.cwd('..')
with FTP('ftp.example.com') as ftp:
ftp.login('user', 'pass')
upload_directory(ftp, './website', '/public_html')Debug Mode
from ftplib import FTP
with FTP('ftp.example.com') as ftp:
ftp.set_debuglevel(2) # Show all FTP commands
ftp.login('username', 'password')
ftp.dir()Summary
ftplib provides full FTP client functionality:
FTP()for plain connections,FTP_TLS()for secureretrbinary()/retrlines()for downloadsstorbinary()/storlines()for uploadscwd(),mkd(),rmd()for directoriesnlst(),dir(),mlsd()for listings
FTP is legacy but still common for file hosting and deployment. Consider SFTP (paramiko) for new projects.
React to this post: