12. Servizi web in Python
![]() |
Gli script Python possono essere eseguiti da un server web. È il server che ascolta le richieste dei client. Dal punto di vista del client, chiamare un servizio web equivale a richiedere l'URL di quel servizio. Il client può essere scritto in qualsiasi linguaggio, compreso Python. Dobbiamo sapere come “comunicare” con un servizio web, ovvero comprendere il protocollo HTTP utilizzato per la comunicazione tra un server web e i suoi client. Questo è lo scopo dei programmi seguenti.
Gli script del servizio web saranno eseguiti dal server web Apache in WampServer. Devono essere collocati in una directory specifica: <WampServer>\bin\apache\apachex.y.z\cgi-bin, dove <WampServer> è la cartella di installazione di WampServer e x.y.z è la versione del server web Apache.
![]() |
Non è sufficiente inserire semplicemente gli script Python nella cartella <cgi-bin>. Lo script deve specificare il percorso dell'interprete Python da utilizzare nella prima riga. Questo percorso è incluso come commento:
I lettori dovrebbero adattare questo percorso al proprio ambiente.
12.1. Applicazione client/server per data e ora
Il nostro primo servizio web sarà un servizio di data e ora: il client riceve la data e l’ora correnti.
12.1.1. Il server
Note:
- Riga 6: Lo script deve generare alcune delle intestazioni HTTP per la risposta al client stesso. Queste verranno aggiunte alle intestazioni HTTP generate dal server Apache stesso. L'intestazione HTTP alla riga 6 comunica al client che una risorsa verrà inviata in formato text/plain, ovvero testo non formattato. Si noti il "\n" alla fine dell'intestazione, che genererà una riga vuota dopo l'intestazione. Questo è obbligatorio: è questa riga vuota che segnala al client HTTP la fine delle intestazioni HTTP nella risposta. Segue la risorsa richiesta dal client, in questo caso testo non formattato;
- riga 18: la risorsa inviata al client è un testo che mostra la data e l'ora correnti.
12.1.2. Due test
Lo script precedente può essere eseguito direttamente dall'interprete Python in una finestra di comando, come abbiamo fatto finora. Questo aiuta a eliminare eventuali errori di sintassi o di runtime. Si ottiene il seguente risultato:
Una volta testato lo script in questo modo, è possibile inserirlo nella directory <cgi-bin> del server Apache (vedere il paragrafo 12). Avviamo l'applicazione WampServer. In questo modo si avvieranno sia il server web Apache che il server di database MySQL. Per ora utilizzeremo solo il server web. Quindi, utilizzando un browser, inserite il seguente URL: http://localhost/cgi-bin/web_02.py:
![]() |
- in [1]: l'URL richiesto;
- in [2]: la risposta visualizzata dal browser;
- in [3]: il codice sorgente ricevuto dal browser web. Si tratta infatti del codice inviato dallo script Python.
Con alcuni strumenti (in questo caso, Firebug, un plugin per il browser Firefox), è possibile accedere alle intestazioni HTTP scambiate con il server. In questo caso, il browser web ha ricevuto le seguenti intestazioni HTTP:
Le righe 7–8 sono riconoscibili come l'intestazione HTTP inviata dallo script Python. Le righe precedenti sono state generate dal server web Apache.
12.1.3. Un client programmato
Ora scriveremo uno script che fungerà da client per il servizio web precedente. Utilizzeremo le funzionalità del modulo httplib, che semplifica la scrittura di client HTTP.
Note:
- Riga 3: Il modulo re è necessario per le espressioni regolari, mentre il modulo httplib serve per le funzioni client HTTP;
- riga 9: viene creata una connessione HTTP utilizzando la porta 80 sull'HOST definito nella riga 6;
- riga 11: il log consente di visualizzare le intestazioni HTTP della richiesta del client e della risposta del server;
- riga 13: viene richiesto l'URL del servizio web. Esistono due modi per richiederlo: utilizzando un comando HTTP GET o POST. La differenza tra i due viene spiegata più avanti. Qui, verrà richiesto utilizzando il comando HTTP GET;
- riga 15: viene letta la risposta del server. Qui si ottiene l'intera risposta: le intestazioni HTTP e la risorsa richiesta dal client. Nella sua risposta, il server potrebbe aver indicato al client di effettuare un reindirizzamento. In questo caso, il client httplib esegue automaticamente il reindirizzamento. La risposta ottenuta è quindi quella risultante dal reindirizzamento;
- riga 17: la risposta è costituita dalle intestazioni HTTP e dal documento richiesto dal client. Per recuperare solo le intestazioni HTTP, utilizzare [response].getHeaders(). Per recuperare il documento, utilizzare [response].read();
- Riga 19: una volta ottenuta la risposta dal server web, la connessione con esso viene chiusa;
- Sappiamo che il documento inviato dal server è una riga di testo nel formato 15/06/11 14:56:36. Righe 22–26: utilizziamo un'espressione regolare per estrarre i vari elementi di questa riga.
12.1.4. Risultati
Note:
- riga 1: le intestazioni HTTP inviate dal client al server web;
- Righe 2–6: le intestazioni HTTP nella risposta del server web;
- Riga 8: il documento inviato dal server;
- Riga 11: il risultato della sua elaborazione;
12.2. Il server recupera i parametri inviati dal client
Nel protocollo HTTP, un client dispone di due metodi per trasmettere i parametri al server web:
- richiede l'URL del servizio nel modulo
GET url?param1=val1¶m2=val2¶m3=val3… HTTP/1.0
dove i valori validi devono essere prima codificati in modo che alcuni caratteri riservati vengano sostituiti dai loro valori esadecimali.
- richiede l'URL del servizio nella forma
quindi, tra le intestazioni HTTP inviate al server, include la seguente intestazione:
Il resto delle intestazioni inviate dal client termina con una riga vuota. Può quindi inviare i propri dati nel formato
dove i valori devono, come nel metodo GET, essere codificati in precedenza. Il numero di caratteri inviati al server deve essere N, dove N è il valore dichiarato nell'intestazione:
12.2.1. Il servizio web
Il seguente servizio web riceve tre parametri dal proprio client: last_name, first_name e age. Li recupera da una struttura simile a un dizionario denominata cgi.FieldStorage fornita dal modulo cgi. Il valore vali di un parametro parami si ottiene utilizzando vali = cgi.FieldStorage().getlist("parami"). Ciò restituisce un array di:
- 0 elementi se il parametro parami non è presente nella richiesta del client;
- 1 elemento se il parametro parami è presente una volta nella richiesta del client;
- n elementi se il parametro parami è presente n volte nella richiesta del client.
Una volta recuperati i parametri, lo script li rinvia al client.
È possibile eseguire un test utilizzando un browser web:
![]() |
In [1], l'URL del servizio web. Si noti la presenza dei tre parametri last_name, first_name, age. In [2], la risposta del servizio web.
12.2.2. Il client GET
Note:
- righe 8–10: i valori dei 3 parametri inviati al servizio web;
- riga 13: questi devono essere codificati. Ciò avviene utilizzando il metodo urlencode del modulo urllib. Questo modulo viene importato alla riga 3. Il metodo accetta come parametro un dizionario {param1:val1, param2:val2, ...};
- riga 15: in una richiesta GET (riga 21), il client deve inserire i parametri codificati alla fine dell'URL del servizio web;
- Le righe seguenti sono già state trattate.
12.2.3. I risultati
Note:
- riga 2: notare la codifica dei parametri (last_name, first_name, age);
- riga 8: la risposta del servizio web.
12.2.4. Il client POST
Il client POST è simile al client GET, tranne per il fatto che i parametri codificati non fanno più parte dell'URL di destinazione. Vengono passati come terzo argomento della richiesta POST (riga 19).
12.2.5. Risultati
Note:
- Nota riga 2: il metodo POST utilizzato dal client per inviare i parametri codificati:
- L'intestazione HTTP Content-Length indica il numero di caratteri che saranno inviati al servizio web;
- questa intestazione HTTP è seguita da una riga vuota che indica la fine delle intestazioni HTTP;
- quindi vengono inviati i 39 caratteri dei parametri codificati.
- Riga 8: la risposta del servizio web.
12.3. Recupero delle variabili d'ambiente da un servizio web
12.3.1. Il servizio web
Lo script CGI Python viene eseguito in un ambiente di sistema dotato di attributi. I suoi attributi e i relativi valori sono disponibili nel dizionario os.environ.
Note:
- Riga 3: È necessario importare il modulo os per accedere alle variabili "di sistema".
Se si esegue direttamente lo script sopra riportato (ovvero come script da console anziché come script CGI), nella console verranno visualizzati i seguenti risultati:
In un browser web (dove viene eseguito lo script CGI), si ottengono i seguenti risultati:
![]() |
Si noti che, a seconda del contesto di esecuzione, l'ambiente ottenuto non è lo stesso.
12.3.2. Il client programmato
12.3.3. Risultati
Si noti che il client programmato non riceve esattamente la stessa risposta del browser web. Questo perché il browser ha inviato al server web delle informazioni che il server ha utilizzato per generare la propria risposta. In questo caso, il client programmato non ha inviato alcuna informazione su se stesso.




