Very fast asynchronous FTP server library providing RFC-959 compliant FTP servers with advanced features including FTPS, IPv6, Unicode support, and flexible authentication systems
—
Server implementations providing different concurrency models for building scalable FTP services. pyftpdlib offers asynchronous, multi-threaded, and multi-process server options to handle various performance requirements and deployment scenarios.
Main asynchronous FTP server using single-process event-driven architecture for maximum efficiency and scalability.
class FTPServer:
# Class attributes
max_cons: int = 512
max_cons_per_ip: int = 0 # 0 = unlimited
def __init__(self, address_or_socket, handler, ioloop=None, backlog=100):
"""
Initialize FTP server.
Parameters:
- address_or_socket: tuple (host, port) or socket object
- handler: FTPHandler class or subclass
- ioloop: IOLoop instance (None = use default)
- backlog: maximum queued connections
"""
@property
def address(self):
"""Get server listening address as (host, port) tuple."""
def serve_forever(self, timeout=None, blocking=True, handle_exit=True, worker_processes=1):
"""
Start serving requests.
Parameters:
- timeout: I/O polling timeout in seconds
- blocking: whether to block until server stops
- handle_exit: whether to handle SIGINT/SIGTERM signals
- worker_processes: number of processes to fork (POSIX only)
"""
def handle_accepted(self, sock, addr):
"""Handle new client connection."""
def close_all(self):
"""Close server and all client connections."""
# Context manager support
def __enter__(self): ...
def __exit__(self, *args): ...Multi-threaded server that spawns a new thread for each client connection, suitable for I/O-bound operations or when using blocking filesystem operations.
class ThreadedFTPServer(FTPServer):
# Class attributes
poll_timeout: float = 1.0
join_timeout: int = 5
refresh_interval: int = 5
def __init__(self, address_or_socket, handler, ioloop=None, backlog=100):
"""Initialize threaded FTP server with same parameters as FTPServer."""Multi-process server that forks worker processes to handle client connections, providing true parallelism and fault isolation. Available on POSIX systems only.
class MultiprocessFTPServer(FTPServer): # POSIX only
# Class attributes
poll_timeout: float = 1.0
join_timeout: int = 5
refresh_interval: int = 5
def __init__(self, address_or_socket, handler, ioloop=None, backlog=100):
"""Initialize multi-process FTP server with same parameters as FTPServer."""from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer
# Setup authorizer and handler
authorizer = DummyAuthorizer()
authorizer.add_user("user", "pass", "/home/user", perm="elradfmwMT")
handler = FTPHandler
handler.authorizer = authorizer
# Create and start server
server = FTPServer(("0.0.0.0", 21), handler)
server.serve_forever()from pyftpdlib.servers import ThreadedFTPServer
# Same setup as above...
server = ThreadedFTPServer(("0.0.0.0", 21), handler)
server.serve_forever()from pyftpdlib.servers import MultiprocessFTPServer
# Same setup as above...
server = MultiprocessFTPServer(("0.0.0.0", 21), handler)
# Fork 4 worker processes
server.serve_forever(worker_processes=4)with FTPServer(("0.0.0.0", 21), handler) as server:
print(f"Starting FTP server on {server.address}")
server.serve_forever()# Limit total connections and per-IP connections
class CustomFTPServer(FTPServer):
max_cons = 256 # Maximum 256 total connections
max_cons_per_ip = 5 # Maximum 5 connections per IP
server = CustomFTPServer(("0.0.0.0", 21), handler)
server.serve_forever()import signal
def signal_handler(signum, frame):
print(f"Received signal {signum}, shutting down...")
server.close_all()
server = FTPServer(("0.0.0.0", 21), handler)
# Custom signal handling
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
# Start server without built-in signal handling
server.serve_forever(handle_exit=False)Install with Tessl CLI
npx tessl i tessl/pypi-pyftpdlib