La convenienza e la versatilità di Python significano che è usato per costruire software in quasi tutti gli ambiti della vita IT. Una nicchia importante è quella dei servizi web, dove la velocità di sviluppo e le metafore flessibili di Python rendono facile ottenere siti web attivi e funzionanti velocemente.
E proprio come si potrebbe immaginare, Python offre un sacco di scelte e latitudine nei framework web, sia piccoli che grandi. Dopo tutto, non tutti i progetti web hanno bisogno di essere su scala aziendale. La maggior parte dovrebbe essere abbastanza grande da portare a termine il lavoro, e non più grande. Questo articolo esamina otto dei più noti framework Python che enfatizzano la semplicità, la leggerezza e l’attenzione.
Bottle
Bottle potrebbe essere considerato una sorta di mini-Flask, poiché è ancora più compatto e succinto di quell’altro “microframework”. A causa del suo minimo ingombro, Bottle è ideale per essere incluso in altri progetti o per consegnare rapidamente piccoli progetti come le API REST. (Flask è discusso più avanti.)
L’intero codice base di Bottle sta in un singolo file e non ha assolutamente dipendenze esterne. Anche così, Bottle è dotato di abbastanza funzionalità per costruire comuni tipi di applicazioni web senza fare affidamento su un aiuto esterno.
Il sistema di routing in Bottle, che mappa gli URL alle funzioni, ha quasi esattamente la stessa sintassi di Flask. Non siete nemmeno limitati ad un set di percorsi cablati; potete crearli dinamicamente. I dati della richiesta e della risposta, i cookie, le variabili della query, i dati del modulo da un’azione POST, le intestazioni HTTP e l’upload dei file possono essere accessibili e manipolati tramite oggetti in Bottle.
Ogni capacità è stata implementata con buona attenzione ai dettagli. Con il caricamento dei file, per esempio, non è necessario rinominare il file se la sua convenzione di denominazione si scontra con il file system di destinazione (come gli slash nel nome su Windows). Bottle può farlo per voi.
Bottle include il suo semplice motore di template HTML. Di nuovo, anche se minimo, il motore di template ha tutto l’essenziale. Le variabili incluse in un template sono rese con HTML sicuro per impostazione predefinita; devi indicare quali variabili sono sicure da riprodurre letteralmente. Se preferite sostituire il motore di template di Bottle con uno diverso, come Jinja2, Bottle vi permette di farlo senza problemi. Io preferisco il semplice sistema di template fornito con Bottle; è veloce, la sua sintassi è senza pretese, e ti permette di mischiare il codice e il testo del template senza eccessiva difficoltà.
Bottle supporta anche più server back-end. Viene fornito con il proprio miniserver integrato per test rapidi, ma supporta anche WSGI generico, un’ampia varietà di server HTTP compatibili con WSGI e il vecchio CGI, se necessario.
Bottle non ha bisogno di così tanta documentazione come altri framework, ma la documentazione non è affatto scarna. Tutte le cose cruciali stanno in una singola (anche se lunga) pagina web. Oltre a questo, troverete una documentazione completa per ogni API, esempi per il deploy su varie infrastrutture, una spiegazione del linguaggio di template integrato, e una serie di ricette comuni.
Come per Flask, è possibile espandere le funzionalità di Bottle manualmente o tramite i plug-in. I plug-in di Bottle non sono neanche lontanamente così numerosi come quelli di Flask, ma ci sono pezzi utili, come l’integrazione con vari livelli di database e l’autenticazione utente di base. Per il supporto asincrono, Bottle può usare uno degli adattatori di server esistenti che funziona in modo asincrono, come aiohttp/uvloop, ma async/await
non è supportato nativamente.
Una conseguenza del minimalismo di Bottle è che alcuni elementi semplicemente non ci sono. La validazione dei moduli, incluse caratteristiche come la protezione CSRF (cross-site request forgery), non è inclusa. Se si vuole costruire un’applicazione web che supporti un alto grado di interazione con l’utente, è necessario aggiungere questo supporto da soli.
Un altro problema con Bottle è che lo sviluppo si è fermato; l’ultimo rilascio, 0.12, è arrivato nel 2013. Detto questo, Bottle continua ad essere mantenuto, e le sue versioni di sviluppo rimangono utilizzabili per la produzione. Gli sviluppatori intendono fornire nuove versioni che eliminano il supporto per le edizioni precedenti di Python.
CherryPy
CherryPy è stato in giro in una forma o nell’altra per quasi 20 anni, ma non ha perso il minimalismo e l’eleganza che lo ha contraddistinto fin dall’inizio.
L’obiettivo di CherryPy, a parte il fatto che contiene solo il minimo necessario per servire le pagine web, è quello di sentirsi, per quanto possibile, non come un “web framework” ma come qualsiasi altro tipo di applicazione Python. Siti come Hulu e Netflix hanno usato CherryPy in produzione perché il framework fornisce una base molto discreta su cui costruire. CherryPy usa i thread in pool sotto il cofano, per meglio supportare gli adattatori server multithreaded.
CherryPy vi permette di mantenere la vostra applicazione web separata dalla logica di base. Per mappare le funzioni della vostra applicazione agli URL o ai percorsi serviti da CherryPy, create una classe in cui gli spazi dei nomi degli oggetti mappano direttamente gli URL che volete servire. Per esempio, la radice del sito web è fornita da una funzione chiamata “index”. I parametri passati a queste funzioni sono usati per gestire le variabili fornite dai metodi GET o POST.
I bit che CherryPy include sono pensati per funzionare come blocchi di costruzione di basso livello. Gli identificatori di sessione e la gestione dei cookie sono inclusi, ma il template HTML no. Come Bottle, CherryPy offre un modo per mappare i percorsi alle directory sul disco per il servizio statico dei file.
CherryPy spesso rinvia ad una libreria di terze parti esistente per supportare una caratteristica piuttosto che fornirla nativamente. Le applicazioni WebSocket, per esempio, non sono supportate direttamente da CherryPy, ma attraverso la libreria ws4py.
La documentazione di CherryPy include un pratico tutorial che spiega i vari aspetti del programma. Non vi porterà attraverso un’applicazione completa end-to-end, a differenza di alcuni tutorial di altri framework, ma è comunque utile. La documentazione è corredata da utili note sulla distribuzione in host virtuali, il reverse proxying tramite Apache e Nginx, e molti altri scenari.
Falcon
Se state costruendo API basate su REST e nient’altro, Falcon è stato fatto proprio per voi. Snello e veloce, con quasi nessuna dipendenza oltre alla libreria standard, Falcon fornisce tutto il necessario per le API REST e niente di più. Falcon 2.0, rilasciato nel 2019, non supporta più Python 2.x e richiede almeno Python 3.5.
Una grande parte del motivo per cui Falcon guadagna l’etichetta “leggero e snello” ha poco a che fare con il numero di linee di codice nel framework. È perché Falcon non impone quasi nessuna struttura propria alle applicazioni. Tutto ciò che un’applicazione Falcon deve fare è indicare quali funzioni corrispondono a quali endpoint API. Restituire JSON da un endpoint comporta poco più che impostare un percorso e restituire i dati tramite la funzione json.dumps
dalla libreria standard di Python. Il supporto per l’async non è ancora arrivato in Falcon, ma si sta lavorando per renderlo possibile in Falcon 3.0.
Falcon impiega anche dei sani default out-of-the-box, quindi sono necessari pochi accorgimenti per la configurazione. Per esempio, i 404 sono sollevati per default per ogni rotta che non è esplicitamente dichiarata. Se volete restituire errori al client, potete sollevare una delle numerose eccezioni fornite con il framework (come HTTPBadRequest
) o usare un’eccezione generica falcon.HTTPError
. Se hai bisogno di una pre-elaborazione o post-elaborazione per una rotta, Falcon fornisce ganci anche per quelli.
L’attenzione di Falcon per le API significa che c’è poco qui per costruire applicazioni web con interfacce utente HTML convenzionali. Non aspettatevi molto in termini di funzioni di elaborazione dei moduli e strumenti di protezione CSRF, per esempio. Detto questo, Falcon fornisce eleganti opzioni per estendere la sua funzionalità, così si possono costruire oggetti più sofisticati. A parte il già citato meccanismo di aggancio, troverete un’interfaccia per creare middleware che può essere utilizzato per avvolgere tutte le API di Falcon.
La documentazione di Falcon è snella rispetto ad altri framework, ma solo perché c’è meno da coprire. La guida per l’utente include una guida formale passo-passo di tutte le principali caratteristiche, insieme ad una sezione di avvio rapido che ti permette di visualizzare codice di esempio con o senza annotazioni.
FastAPI
Il nome di FastAPI è una buona sintesi di ciò che fa. È costruito per creare endpoint API velocemente, e funziona anche velocemente.
FastAPI fa uso del progetto Starlette per il suo nucleo di rete ad alta velocità, ma non è necessario conoscere gli interni di Starlette per usare FastAPI. Si definiscono gli endpoint allo stesso modo di un’applicazione Flask o Bottle – si usano i decoratori per indicare quali funzioni gestiscono quali percorsi – e poi si restituiscono dizionari che vengono tradotti automaticamente in JSON.
Si può facilmente sovrascrivere come le cose vengono restituite. Per esempio, se volete restituire HTML/XML da alcuni endpoint, potete farlo semplicemente restituendo un oggetto Response
personalizzato. Se volete aggiungere un middleware personalizzato, potete inserire qualsiasi cosa che segua lo standard ASGI.
FastAPI fa uso del type hinting di Python per fornire vincoli sui tipi di dati che le rotte accettano. Per esempio, se avete una rotta con il tipo Optional
, FastAPI rifiuterà qualsiasi invio eccetto gli interi. Non devi aggiungere codice di validazione dei dati ai tuoi endpoint; puoi semplicemente usare i type hints e lasciare che FastAPI faccia il lavoro.
Naturalmente, alcune cose sono rimaste fuori. Non c’è un motore di template HTML nativo, per esempio, ma non mancano soluzioni di terze parti per colmare questa lacuna. Lo stesso vale per la connettività al database, ma la documentazione contiene dettagli su come convincere certi ORM (ad esempio Peewee) a lavorare con i comportamenti asincroni di FastAPI.
Flask
Molte discussioni sui framework web Python iniziano con Flask, e per buone ragioni. Flask è un framework ben consolidato, ben compreso, facile da usare e abbastanza stabile. È quasi impossibile sbagliare usando Flask per un progetto web leggero o un’API REST di base, ma dovrete affrontare un lavoro pesante se cercate di costruire qualcosa di più grande.
Il fascino centrale di Flask è la sua bassa barriera d’ingresso. Un’applicazione di base “hello world” può essere impostata in meno di 10 righe di Python. Flask include un sistema di template HTML ampiamente usato, Jinja2, per rendere facile il rendering del testo, ma Jinja2 può essere sostituito con qualsiasi numero di altri motori di template (come Mustache) o si può creare il proprio.
In nome della semplicità, Flask omette sottigliezze come un livello di dati o ORM, e non offre disposizioni per la validazione dei moduli. Tuttavia, Flask può essere espanso attraverso le estensioni, di cui ci sono dozzine, che coprono molti casi d’uso comuni come il caching, la gestione e la validazione dei moduli e la connettività del database. Questo design “lean-by-default” vi permette di iniziare a progettare un’applicazione Flask con il minimo assoluto di funzionalità, per poi aggiungere solo i pezzi di cui avete bisogno quando ne avete bisogno.
La documentazione di Flask è geniale e facile da leggere. Il documento di avvio rapido fa un eccellente lavoro per farvi iniziare, spiegando anche il significato delle scelte predefinite per una semplice applicazione Flask, e i documenti API sono pieni di buoni esempi. Eccellente è anche la collezione di Flash snippets, che sono esempi rapidi e sporchi di come realizzare compiti specifici, come ad esempio come restituire un oggetto se esiste o un errore 404 se non esiste.
Flask ha raggiunto la sua pietra miliare 1.0 nel 2018, con Python 2.6 e Python 3.3 come versioni minime supportate, e con molti dei suoi comportamenti finalmente fissati nella pietra. Flask non supporta esplicitamente la sintassi asincrona di Python, ma una variazione API-compatibile di Flask chiamata Quart è stata scorporata per soddisfare questa richiesta.
Pyramid
Piccolo e leggero, Pyramid è adatto a compiti come esporre il codice Python esistente come API REST, o fornire il nucleo di un progetto web in cui lo sviluppatore fa la maggior parte del lavoro pesante.
“Pyramid vi permetterà di diventare produttivi rapidamente, e crescerà con voi,” dice la documentazione. “Un buon modo per descrivere il minimalismo di Pyramid sarebbe “libero dalla politica”, un termine usato nella sezione della documentazione che discute come Pyramid si pone rispetto ad altri framework web. Fondamentalmente, “free of policy” significa che il database o il linguaggio di template che si sceglie di usare non è una preoccupazione di Pyramid.
Molto poco lavoro è necessario per costruire un’applicazione Pyramid di base. Come con Bottle e Flask, un’applicazione Pyramid può consistere in un singolo file Python, a parte i file per il framework stesso. Una semplice API ad una via non richiede più di una dozzina di righe di codice. La maggior parte è boilerplate come le dichiarazioni from … import
e l’impostazione del server WSGI.
Di default, Pyramid include diversi elementi che sono comuni nelle applicazioni web, ma sono forniti come componenti da cucire insieme, non come soluzioni complete. Il supporto per le sessioni utente, per esempio, è anche dotato di protezione CSRF. Ma il supporto per gli account utente, come i login o la gestione degli account, non fa parte dell’accordo. Dovrete rollarlo voi stessi o aggiungerlo attraverso un plug-in. Lo stesso vale per la gestione dei moduli e le connessioni al database.
Pyramid fornisce anche un modo per creare modelli da precedenti progetti Pyramid per riutilizzare il lavoro precedente. Questi modelli, chiamati “scaffold”, generano un’applicazione Pyramid con un semplice routing e alcuni modelli HTML/CSS di partenza. Gli scaffold in bundle includono un progetto di esempio iniziale e un progetto che si connette ai database tramite la popolare libreria Python SQLAlchemy.
Gli snelli strumenti di test e debug di Pyramid fanno il loro dovere. Inserite l’estensione debugtoolbar
in un’applicazione Pyramid e otterrete un’icona cliccabile su ogni pagina web che genera dettagli sull’esecuzione dell’applicazione, incluso un traceback dettagliato in caso di errori. Sono presenti anche la registrazione e i test unitari.
La documentazione di Pyramid è eccellente. Oltre a un rapido tour delle basi e un walk-through in stile tutorial, troverete una serie di tutorial contribuiti dalla comunità e un libro di ricette comuni. Quest’ultimo include tecniche di distribuzione per una serie di ambienti di destinazione, da Google App Engine a Nginx.
Pyramid supporta sia Python 2 che Python 3, ma non usa la sintassi asincrona di Python 3. Se vuoi sfruttare l’async in Pyramid, vedi il progetto aiopyramid, che include un’impalcatura per un’applicazione “hello world” alimentata in async.
Sanic
Progettato per la velocità e la semplicità, Sanic funziona con Python 3.6 o superiore e usa la sintassi async/await
di Python (disponibile a partire da Python 3.5) per permettervi di creare applicazioni web efficienti.
Come per Flask o Bottle, un “hello world” di base di Sanic contiene circa 10 righe di codice, la maggior parte delle quali sono importazioni e altra documentazione. La differenza chiave è che le rotte delle applicazioni devono essere dichiarate come funzioni async def
, e dovete usare await
per invocare queste funzioni nel vostro codice asincrono. Se avete scritto applicazioni asincrone in precedenza, avete già la parte più difficile sotto la cintura.
Molti dei meccanismi che Sanic usa per gestire connessioni e risposte vi saranno familiari. Richieste e risposte sono solo oggetti con proprietà dall’aspetto familiare, come file caricati, moduli, oggetti JSON, intestazioni e così via.
Applicazioni con molti percorsi diventano ingombranti da gestire. Sanic affronta questo problema con i “blueprints”, oggetti che possono descrivere gruppi di rotte e permettono di gestirle tramite un’interfaccia di alto livello. Invece di scrivere esplicitamente ogni rotta, o di usare un eccesso di rotte con variabili, potete scrivere alcuni blueprints per descrivere genericamente come funzionano le rotte nella vostra applicazione (ad esempio, /object/object_id/action
). I blueprint possono avere un middleware comune, che è utile se vuoi applicare funzionalità di gestione ad alcune rotte ma non ad altre.
Sanic funziona anche con protocolli diversi da HTTP. Gli endpoint WebSocket richiedono solo un decoratore diverso e un po’ più di logica interna (ad esempio, l’attesa e la gestione delle risposte). Protocolli di rete personalizzati possono essere supportati sottoclassificando asyncio.protocol
.
Sanic lascia deliberatamente fuori funzionalità come la connettività del database e il templating HTML, mentre mantiene le caratteristiche che uno userebbe per inserire queste capacità: middleware, configurazione centralizzata dell’applicazione, e così via.
Tornado
Tornado è un altro piccolo framework mirato a un caso d’uso specifico: applicazioni di rete asincrone. Tornado è adatto alla creazione di servizi che aprono un gran numero di connessioni di rete e le mantengono in vita, cioè qualsiasi cosa che coinvolga i WebSockets o un lungo polling. Tornado 6.0 richiede Python 3.5 o superiore, e abbandona completamente il supporto a Python 2.
Come Bottle o Falcon, Tornado omette caratteristiche estranee al suo scopo centrale. Tornado ha un sistema integrato di template per generare HTML e altri output, e fornisce meccanismi per l’internazionalizzazione, la gestione dei moduli, l’impostazione dei cookie, l’autenticazione dell’utente e la protezione CSRF. Ma lascia fuori caratteristiche, come la validazione dei moduli e un ORM, che sono principalmente per le applicazioni web rivolte all’utente.
Tornado eccelle nel fornire infrastrutture alle applicazioni che hanno bisogno di uno stretto controllo sul networking asincrono. Per esempio, Tornado fornisce non solo un server HTTP asincrono integrato, ma anche un client HTTP asincrono. Pertanto, Tornado è adatto alla costruzione di applicazioni, come un web scraper o un bot, che interrogano altri siti in parallelo e agiscono sui dati restituiti.
Se volete creare un’applicazione che utilizza protocolli diversi da HTTP, Tornado vi copre. Tornado fornisce l’accesso a connessioni TCP di basso livello e a socket per utility come i resolver DNS, così come a servizi di autenticazione di terze parti, e supporta l’interoperabilità con altri framework attraverso lo standard WSGI. La documentazione, che è piccola ma non scarsa, include ampi esempi per realizzare tutto questo.
Tornado sfrutta e completa le funzionalità native di Python per i comportamenti asincroni. Se state usando Python 3.5, Tornado supporta le parole chiave integrate async
e await
, che promettono di dare alle applicazioni un aumento di velocità. Potete anche usare futures o callback per gestire le risposte agli eventi.
Tornado fornisce una libreria di primitive di sincronizzazione – maphores, lock, e così via – per coordinare gli eventi tra coroutine asincrone. Notate che Tornado normalmente funziona a thread singolo, quindi queste primitive non sono le stesse dei loro omonimi di threading. Tuttavia, se volete eseguire Tornado in processi paralleli per sfruttare più socket e core, sono disponibili strumenti per farlo.
La documentazione di Tornado copre ogni concetto principale del framework e tutte le principali API del modello. Sebbene includa un’applicazione di esempio (un web crawler), è principalmente per dimostrare il modulo di accodamento di Tornado.