L’autore ha selezionato il Fondo per il Software Libero e Open Source per ricevere una donazione nell’ambito del programma Scrivi per Donare.
Introduzione
Flask è un framework web leggero per Python che fornisce utili strumenti e funzionalità per la creazione di applicazioni web nel linguaggio Python.
Quando sviluppi un’applicazione web, inevitabilmente ti imbatterai in situazioni in cui l’applicazione si comporta in modo contrario a quanto previsto. Potresti scrivere male una variabile, usare male un ciclo for
, o costruire un’istruzione if
in modo da sollevare un’eccezione Python, come chiamare una funzione prima di dichiararla, o semplicemente cercare una pagina che non esiste. Troverai più facile e fluido sviluppare le tue applicazioni Flask se impari a gestire errori ed eccezioni in modo appropriato.
In questo tutorial, costruirai una piccola applicazione web che dimostra come gestire gli errori comuni che si incontrano durante lo sviluppo di un’applicazione web. Creerai pagine di errore personalizzate, utilizzerai il debugger di Flask per risolvere le eccezioni e utilizzerai la registrazione per tracciare gli eventi nella tua applicazione.
Prerequisiti
-
Un ambiente di programmazione locale Python 3. Puoi seguire il tutorial per la tua distribuzione nella serie Come Installare e Configurare un Ambiente di Programmazione Locale per Python 3. In questo tutorial chiameremo la nostra directory del progetto
flask_app
. -
Una comprensione dei concetti di base di Flask, come route, funzioni di visualizzazione e template. Se non hai familiarità con Flask, consulta Come Creare la Tua Prima Applicazione Web Usando Flask e Python e Come Utilizzare Template in un’Applicazione Flask.
-
Capacità di comprendere i concetti di base di HTML. Puoi rivedere la nostra serie di tutorial Come Costruire un Sito Web con HTML per conoscere le basi.
Passo 1 — Utilizzare il Debugger di Flask
In questo passo, creerai un’applicazione con alcuni errori e la eseguirai senza la modalità di debug per vedere come risponde. Poi la eseguirai con la modalità di debug attiva e utilizzerai il debugger per risolvere gli errori dell’applicazione.
Con il tuo ambiente di programmazione attivato e Flask installato, apri un file chiamato app.py
per la modifica all’interno della directory flask_app
:
Aggiungi il seguente codice all’interno del file app.py
:
Nel codice sopra, prima importi la classe Flask
dal pacchetto flask
. Poi crei un’istanza di applicazione Flask chiamata app
. Utilizzi il decoratore @app.route()
per creare una funzione vista chiamata index()
, che chiama la funzione render_template()
come valore di ritorno, che a sua volta rende un template chiamato index.html
. Ci sono due errori in questo codice: il primo è che non hai importato la funzione render_template()
, e il secondo è che il file template index.html
non esiste.
Salva e chiudi il file.
Successivamente, informa Flask sull’applicazione utilizzando la variabile d’ambiente FLASK_APP
con il seguente comando (su Windows, usa set
invece di export
):
Poi esegui il server dell’applicazione utilizzando il comando flask run
:
Vedrai le seguenti informazioni nel tuo terminale:
Output * Serving Flask app 'app' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Questo output fornisce le seguenti informazioni:
-
L’applicazione Flask servita (
app.py
in questo caso) -
L’ambiente, che qui è
production
. Il messaggio di avviso sottolinea che questo server non è destinato a una distribuzione in produzione. Stai utilizzando questo server per lo sviluppo, quindi puoi ignorare questo avviso, ma per ulteriori informazioni, consulta la pagina Opzioni di Distribuzione nella documentazione di Flask. Puoi anche dare un’occhiata a questo tutorial sulla distribuzione di Flask con Gunicorn, o questo con uWSGI, oppure puoi utilizzare DigitalOcean App Platform per distribuire la tua applicazione Flask seguendo il Come Distribuire un’App Flask Utilizzando Gunicorn su App Platform tutorial. -
La modalità di debug è disattivata, il che significa che il debugger di Flask non è in esecuzione e non riceverai messaggi di errore utili nella tua applicazione. In un ambiente di produzione, la visualizzazione di errori dettagliati espone la tua applicazione a vulnerabilità di sicurezza.
-
Il server è in esecuzione sull’URL
http://127.0.0.1:5000/
. Per arrestare il server, utilizzaCTRL+C
, ma non farlo ancora.
Ora, visita la pagina index utilizzando il tuo browser:
http://127.0.0.1:5000/
Vedrai un messaggio che assomiglia al seguente:
OutputInternal Server Error
The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.
Questo è l’500 Internal Server Error, che è una risposta di errore del server che indica che il server ha incontrato un errore interno nel codice dell’applicazione.
Nel terminale, vedrai il seguente output:
Output[2021-09-12 15:16:56,441] ERROR in app: Exception on / [GET]
Traceback (most recent call last):
File "/home/abd/.local/lib/python3.9/site-packages/flask/app.py", line 2070, in wsgi_app
response = self.full_dispatch_request()
File "/home/abd/.local/lib/python3.9/site-packages/flask/app.py", line 1515, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/abd/.local/lib/python3.9/site-packages/flask/app.py", line 1513, in full_dispatch_request
rv = self.dispatch_request()
File "/home/abd/.local/lib/python3.9/site-packages/flask/app.py", line 1499, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
File "/home/abd/python/flask/series03/flask_app/app.py", line 8, in index
return render_template('index.html')
NameError: name 'render_template' is not defined
127.0.0.1 - - [12/Sep/2021 15:16:56] "GET / HTTP/1.1" 500 -
Il traceback sopra riportato attraversa il codice che ha attivato l’errore interno del server. La riga NameError: name 'render_template' is not defined
fornisce la causa radice del problema: la funzione render_template()
non è stata importata.
Come puoi vedere qui, devi andare al terminale per risolvere gli errori, il che non è conveniente.
Puoi avere un’esperienza migliore nella risoluzione dei problemi abilitando la modalità di debug nel tuo server di sviluppo. Per farlo, arresta il server con CTRL+C
e imposta la variabile d’ambiente FLASK_ENV
su development
, così puoi eseguire l’applicazione in modalità di sviluppo (che abilita il debugger), utilizzando il seguente comando (su Windows, usa set
invece di export
):
Esegui il server di sviluppo:
Nel terminale vedrai un output simile al seguente:
Output * Serving Flask app 'app' (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 120-484-907
Qui puoi notare che l’ambiente è ora development
, la modalità debug è attiva e il debugger è attivo. Il Debugger PIN
è un PIN che devi utilizzare per sbloccare la console nel tuo browser (una shell Python interattiva a cui puoi accedere cliccando sull’icona del terminale racchiusa nell’immagine qui sotto).
Aggiorna la pagina index nel tuo browser e vedrai la seguente pagina:
Qui, l’errore viene visualizzato in un modo più facile da capire. Il primo titolo ti fornisce il nome dell’eccezione Python che ha causato il problema (NameError
in questo caso). La seconda riga ti dà la ragione diretta (render_template()
non è definito, il che significa che non è stato importato in questo caso). Seguendo questo, hai la traccia attraverso il codice interno di Flask che è stato eseguito. Leggi la traccia dal basso verso l’alto, perché l’ultima riga della traccia di solito contiene le informazioni più utili.
Nota:
L’icona del terminale circondata ti permette di eseguire codice Python nel browser su diversi frame. Questo è utile quando vuoi controllare il valore di una variabile come faresti in una shell Python interattiva. Quando clicchi sull’icona del terminale, dovrai digitare il codice PIN del Debugger che hai ottenuto quando hai avviato il server. Non avrai bisogno di questa shell interattiva in questo tutorial.
Per risolvere questo problema di NameError
, lascia il server in esecuzione, apri una nuova finestra del terminale, attiva il tuo ambiente e apri il file app.py
:
Modifica il file come segue:
Salva e chiudi il file.
Qui hai importato la funzione render_template()
che mancava.
Con il server di sviluppo in esecuzione, aggiorna la pagina index nel tuo browser.
Questa volta vedrai una pagina di errore con informazioni simili a queste:
Outputjinja2.exceptions.TemplateNotFound
jinja2.exceptions.TemplateNotFound: index.html
Questo messaggio di errore indica che il template index.html
non esiste.
Per risolvere questo problema, creerai un file template base.html
da cui altri template erediteranno per evitare la ripetizione di codice, quindi un template index.html
che estende il template base.
Crea la directory templates
, che è la directory in cui Flask cerca i file dei template. Quindi apri un file base.html
utilizzando il tuo editor preferito:
Aggiungi il seguente codice al tuo file base.html
:
Salva e chiudi il file.
Questo template base contiene tutto il codice HTML di base che dovrai riutilizzare nei tuoi altri template. Il blocco title
sarà sostituito per impostare un titolo per ogni pagina, e il blocco content
sarà sostituito con il contenuto di ogni pagina. La barra di navigazione ha due collegamenti, uno per la pagina index dove utilizzi la funzione helper url_for()
per collegarti alla funzione di visualizzazione index()
, e l’altro per una pagina About se scegli di includerne una nella tua applicazione.
Successivamente, apri un file modello chiamato index.html
, che erediterà dal modello base.
Aggiungi il seguente codice:
Salva e chiudi il file.
Nel codice sopra, estendi il modello base e sovrascrivi il blocco content
. Quindi imposti un titolo della pagina e lo visualizzi in un’intestazione H1
utilizzando il blocco title
, e visualizzi un saluto in un’intestazione H2
.
Con il server di sviluppo in esecuzione, aggiorna la pagina index nel tuo browser.
Vedrai che l’applicazione non mostra più errori e la pagina index viene visualizzata come previsto.
Ora hai utilizzato la modalità di debug e visto come gestire i messaggi di errore. Successivamente, interromperai una richiesta per rispondere con un messaggio di errore a tua scelta e vedrai come rispondere con pagine di errore personalizzate.
Passo 2 — Creazione di Pagine di Errore Personalizzate
In questo passo, imparerai come interrompere le richieste e rispondere con un messaggio di errore HTTP 404 per quando l’utente richiede dati che non esistono sul server. Imparerai anche come creare pagine di errore personalizzate per errori HTTP comuni, come l’errore 404 Not Found
e l’errore 500 Internal Server Error
.
Per dimostrare come interrompere le richieste e rispondere con una pagina di errore HTTP 404 personalizzata, creerai una pagina che visualizza alcuni messaggi. Se il messaggio richiesto non esiste, risponderai con un errore 404.
Per prima cosa, apri il tuo file app.py
per aggiungere una nuova route per la pagina dei messaggi:
Aggiungi la seguente route alla fine del file:
Salva e chiudi il file.
Nella route sopra, hai una variabile URL idx
. Questo è l’indice che determinerà quale messaggio verrà visualizzato. Ad esempio, se l’URL è /messages/0
, il primo messaggio (Message Zero
) verrà visualizzato. Utilizzi il int
converter per accettare solo numeri interi positivi, poiché le variabili URL hanno valori stringa per default.
All’interno della funzione di visualizzazione message()
, hai una lista Python regolare chiamata messages
con tre messaggi. (In uno scenario reale, questi messaggi provenienti da un database, un’API o un’altra fonte di dati esterna.) La funzione restituisce una chiamata alla funzione render_template()
con due argomenti, message.html
come file modello, e una variabile message
che verrà passata al modello. Questa variabile avrà un elemento dalla lista messages
a seconda del valore della variabile idx
nell’URL.
Successivamente apri un nuovo file modello message.html
:
Aggiungi il seguente codice:
Salva e chiudi il file.
Nel codice sopra, estendi il template di base e sovrascrivi il blocco content
. Aggiungi un titolo (Messages
) in un’intestazione H1 e visualizza il valore della variabile message
in un’intestazione H2.
Con il server di sviluppo in esecuzione, visita i seguenti URL nel tuo browser:
http://127.0.0.1:5000/messages/0
http://127.0.0.1:5000/messages/1
http://127.0.0.1:5000/messages/2
http://127.0.0.1:5000/messages/3
Noterai che l’H2 contiene il testo Message Zero
, Message One
o Message Two
rispettivamente in ciascuno dei primi tre URL. Tuttavia, sul quarto URL, il server risponderà con un messaggio di errore IndexError: list index out of range
. In un ambiente di produzione, la risposta sarebbe stata un 500 Internal Server Error
, ma la risposta appropriata qui è un 404 Not Found
per indicare che il server non può trovare un messaggio con un indice di 3
.
Puoi rispondere con un errore 404
utilizzando la funzione helper abort()
di Flask. Per farlo, apri il file app.py
:
Modifica la prima riga per importare la funzione abort()
. Quindi modifica la funzione di visualizzazione message()
aggiungendo una clausola try ... except
come mostrato nei parti evidenziate di seguito:
Salva e chiudi il file.
Nel codice sopra, importi la funzione abort()
, che usi per interrompere la richiesta e rispondere con un errore. Nella funzione di visualizzazione message()
, usi una clausola try ... except
per racchiudere la funzione. Prima provi a restituire il template messages
con il messaggio che corrisponde all’indice nell’URL. Se l’indice non ha un messaggio corrispondente, verrà sollevata l’eccezione IndexError
. Poi usi la clausola except
per catturare quell’errore e usi abort(404)
per interrompere la richiesta e rispondere con un errore HTTP 404 Not Found
.
Con il server di sviluppo in esecuzione, usa il tuo browser per rivisitare l’URL che ha risposto con un IndexError
in precedenza (o visita qualsiasi URL con un indice maggiore di 2):
http://127.0.0.1:5000/messages/3
Vedrai la seguente risposta:
Not Found
The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
Ora hai un messaggio di errore migliore che indica che il server non ha trovato il messaggio richiesto.
Successivamente, creerai un template per la pagina di errore 404 e uno per la pagina di errore 500.
Prima, registrerai una funzione con il decoratore speciale @app.errorhandler()
come gestore per l’errore 404
. Apri il file app.py
per la modifica:
nano app.py
Modifica il file aggiungendo la parte evidenziata come segue:
Salva e chiudi il file.
Qui utilizzi il decoratore @app.errorhandler()
per registrare la funzione page_not_found()
come gestore di errore personalizzato. La funzione accetta l’errore come argomento e restituisce una chiamata alla funzione render_template()
con un modello chiamato 404.html
. Creerai questo modello in seguito e puoi utilizzare un altro nome se lo desideri. Restituisci anche l’intero 404
dopo la chiamata a render_template()
. Questo indica a Flask che il codice di stato nella risposta deve essere 404
. Se non lo aggiungi, il codice di stato di risposta predefinito sarà 200
, il che significa che la richiesta è riuscita.
Successivamente, apri un nuovo modello 404.html
:
Aggiungi il seguente codice:
Salva e chiudi il file.
Come qualsiasi altro modello, estendi il modello di base, sostituisci il contenuto dei blocchi content
e title
e aggiungi il tuo codice HTML. Qui hai un’intestazione <h1>
come titolo, un tag <p>
con un messaggio di errore personalizzato che informa l’utente che la pagina non è stata trovata, e un messaggio utile per gli utenti che potrebbero aver inserito manualmente l’URL.
Puoi utilizzare qualsiasi HTML, CSS e JavaScript desideri nelle tue pagine di errore allo stesso modo in cui lo faresti in altri modelli.
Con il server di sviluppo in esecuzione, utilizza il tuo browser per rivisitare il seguente URL:
http://127.0.0.1:5000/messages/3
Vedrai che la pagina ora ha la barra di navigazione presente nel modello di base e il messaggio di errore personalizzato.
Allo stesso modo, puoi aggiungere una pagina di errore personalizzata per i tuoi errori 500 Internal Server Error
. Apri il file app.py
:
Aggiungi il seguente gestore di errore sotto il gestore di errore 404
:
Qui utilizzi lo stesso schema che hai usato per il gestore di errore 404
. Utilizzi il decoratore app.errorhandler()
con un argomento 500
per trasformare una funzione chiamata internal_error()
in un gestore di errore. Renderizzi un template chiamato 500.html
e rispondi con un codice di stato 500
.
Poi, per dimostrare come verrà presentato l’errore personalizzato, aggiungi una route che risponde con un errore HTTP 500
alla fine del file. Questa route darà sempre un 500 Internal Server Error
indipendentemente dal fatto che il debugger sia in esecuzione o meno:
Qui crei una route /500
e utilizzi la funzione abort()
per rispondere con un errore HTTP 500
.
Salva e chiudi il file.
Successivamente, apri il nuovo template 500.html
:
Aggiungi il seguente codice a esso:
Salva e chiudi il file.
Qui, fai la stessa cosa che hai fatto con il template 404.html
. Estendi il template di base e sostituisci il blocco del contenuto con un titolo e due messaggi personalizzati che informano l’utente riguardo l’errore interno del server.
Con il server di sviluppo in esecuzione, visita la route che risponde con un errore 500
:
http://127.0.0.1:5000/500
La tua pagina personalizzata apparirà al posto della pagina di errore generica.
Ora sai come utilizzare pagine di errore personalizzate per errori HTTP nella tua applicazione Flask. Successivamente, imparerai come utilizzare il logging per tracciare gli eventi nella tua applicazione. Il tracciamento degli eventi ti aiuta a comprendere il comportamento del tuo codice, il che a sua volta facilita lo sviluppo e la risoluzione dei problemi.
Passo 3 — Utilizzare il Logging per Tracciare Eventi nella Tua Applicazione
In questo passo, utilizzerai il logging per tracciare gli eventi che si verificano quando il server è in esecuzione e l’applicazione è in uso, il che ti aiuta a vedere cosa sta succedendo nel tuo codice dell’applicazione per poter risolvere più facilmente gli errori.
Hai già visto i log ogni volta che il server di sviluppo è in esecuzione, che di solito hanno questo aspetto:
127.0.0.1 - - [21/Sep/2021 14:36:45] "GET /messages/1 HTTP/1.1" 200 -
127.0.0.1 - - [21/Sep/2021 14:36:52] "GET /messages/2 HTTP/1.1" 200 -
127.0.0.1 - - [21/Sep/2021 14:36:54] "GET /messages/3 HTTP/1.1" 404 -
In questi log, puoi vedere le seguenti informazioni:
127.0.0.1
: L’host su cui il server era in esecuzione.[21/Set/2021 14:36:45]
: La data e l’ora della richiesta.GET
: Il metodo di richiesta HTTP. In questo caso,GET
viene utilizzato per recuperare dati./messages/2
: Il percorso richiesto dall’utente.HTTP/1.1
: La versione HTTP.200
o404
: Il codice di stato della risposta.
Questi log ti aiutano a diagnosticare problemi che si verificano nella tua applicazione. Puoi registrare ulteriori informazioni quando desideri conoscere maggiori dettagli su determinate richieste utilizzando il logger app.logger
fornito da Flask.
Con la registrazione, puoi utilizzare diverse funzioni per segnalare informazioni su diversi livelli di registrazione. Ogni livello indica un evento accaduto con un certo grado di gravità. Le seguenti funzioni possono essere utilizzate:
app.logger.debug()
: Per informazioni dettagliate sull’evento.app.logger.info()
: Conferma che le cose funzionano come previsto.app.logger.warning()
: Indicazione che qualcosa di imprevisto è accaduto (come “spazio su disco basso”), ma l’applicazione funziona come previsto.app.logger.error()
: Si è verificato un errore in qualche parte dell’applicazione.app.logger.critical()
: Un errore critico; l’intera applicazione potrebbe smettere di funzionare.
Per dimostrare come utilizzare il logger Flask, apri il tuo file app.py
per la modifica per registrare alcuni eventi:
Modifica la funzione di visualizzazione message()
in modo che appaia come segue:
Salva e chiudi il file.
Qui, hai registrato alcuni eventi a diversi livelli. Utilizzi app.logger.info()
per registrare un evento che funziona come previsto (che è un livello INFO
). Utilizzi app.logger.debug()
per informazioni dettagliate (DEBUG
level), specificando che l’applicazione sta ora ricevendo un messaggio con un indice specifico. Poi utilizzi app.logger.error()
per registrare il fatto che è stata sollevata un’eccezione IndexError
con l’indice specifico che ha causato il problema (ERROR
level, perché si è verificato un errore).
Visita il seguente URL:
http://127.0.0.1:5000/messages/1
Vedrai le seguenti informazioni nel terminale dove è in esecuzione il tuo server:
Output
[2021-09-21 15:17:02,625] INFO in app: Building the messages list...
[2021-09-21 15:17:02,626] DEBUG in app: Get message with index: 1
127.0.0.1 - - [21/Sep/2021 15:17:02] "GET /messages/1 HTTP/1.1" 200 -
Qui vedi il messaggio INFO
app.logger.info()
registra, e il messaggio DEBUG
con il numero di indice che hai registrato utilizzando app.logger.debug()
.
Ora visita un URL per un messaggio che non esiste:
http://127.0.0.1:5000/messages/3
Vedrai le seguenti informazioni nel terminale:
Output[2021-09-21 15:33:43,899] INFO in app: Building the messages list...
[2021-09-21 15:33:43,899] DEBUG in app: Get message with index: 3
[2021-09-21 15:33:43,900] ERROR in app: Index 3 is causing an IndexError
127.0.0.1 - - [21/Sep/2021 15:33:43] "GET /messages/3 HTTP/1.1" 404 -
Come puoi vedere, hai log INFO
e DEBUG
che hai visto prima, e un nuovo log ERROR
perché un messaggio con indice 3
non esiste.
La registrazione di eventi, informazioni dettagliate e errori ti aiuta a identificare dove qualcosa è andato storto e rende la risoluzione dei problemi più facile.
Hai imparato in questo passaggio come utilizzare il logger di Flask. Consulta Come Utilizzare il Logging in Python 3 per una migliore comprensione del logging. Per un approfondimento sul logging, vedi la documentazione del logging di Flask e la documentazione di Python per il logging.
Conclusione
Ora sai come utilizzare la modalità debug in Flask e come risolvere e correggere alcuni errori comuni che potresti incontrare durante lo sviluppo di un’applicazione web Flask. Hai anche creato pagine di errore personalizzate per gli errori HTTP comuni e hai utilizzato il logger di Flask per tracciare gli eventi nella tua applicazione, aiutandoti a ispezionare e capire come si comporta la tua applicazione.
Se desideri leggere di più su Flask, consulta la pagina tematica di Flask.
Source:
https://www.digitalocean.com/community/tutorials/how-to-handle-errors-in-a-flask-application