12. Serviços Web em Python
![]() |
Os scripts Python podem ser executados por um servidor web. É o servidor que irá receber os pedidos dos clientes. Do ponto de vista do cliente, chamar um serviço web equivale a solicitar o URL desse serviço. O cliente pode ser escrito em qualquer linguagem, incluindo Python. Precisamos de saber como «comunicar» com um serviço web, ou seja, compreender o protocolo HTTP utilizado para a comunicação entre um servidor web e os seus clientes. Este é o objetivo dos programas seguintes.
Os scripts do serviço web serão executados pelo servidor web Apache no WampServer. Devem ser colocados num diretório específico: <WampServer>\bin\apache\apachex.y.z\cgi-bin, onde <WampServer> é a pasta de instalação do WampServer e x.y.z é a versão do servidor web Apache.
![]() |
Não basta simplesmente colocar os scripts Python na pasta <cgi-bin>. O script deve especificar o caminho para o interpretador Python a ser utilizado na primeira linha. Este caminho é incluído como um comentário:
Os leitores devem adaptar este caminho ao seu próprio ambiente.
12.1. Aplicação de data e hora cliente/servidor
O nosso primeiro serviço web será um serviço de data e hora: o cliente recebe a data e a hora atuais.
12.1.1. O servidor
Notas:
- Linha 6: O script deve gerar alguns dos cabeçalhos HTTP para a resposta ao próprio cliente. Estes serão adicionados aos cabeçalhos HTTP gerados pelo próprio servidor Apache. O cabeçalho HTTP na linha 6 indica ao cliente que um recurso será enviado no formato text/plain, ou seja, texto sem formatação. Repare no "\n" no final do cabeçalho, que irá gerar uma linha em branco após o cabeçalho. Isto é obrigatório: é esta linha em branco que sinaliza ao cliente HTTP o fim dos cabeçalhos HTTP na resposta. Segue-se o recurso solicitado pelo cliente, neste caso texto sem formatação;
- linha 18: o recurso enviado ao cliente é texto que exibe a data e a hora atuais.
12.1.2. Dois testes
O script anterior pode ser executado diretamente pelo interpretador Python numa janela de comando, tal como temos feito até agora. Isto ajuda a eliminar quaisquer erros de sintaxe ou de tempo de execução. Obtém-se o seguinte resultado:
Depois de o script ter sido testado desta forma, pode ser colocado no diretório <cgi-bin> do servidor Apache (ver parágrafo 12). Vamos iniciar a aplicação WampServer. Isto inicia tanto um servidor web Apache como um servidor de base de dados MySQL. Por enquanto, vamos utilizar apenas o servidor web. Em seguida, utilizando um navegador, introduza o seguinte URL: http://localhost/cgi-bin/web_02.py:
![]() |
- em [1]: o URL solicitado;
- em [2]: a resposta apresentada pelo navegador;
- em [3]: o código-fonte recebido pelo navegador. Este é, de facto, o código enviado pelo script Python.
Com certas ferramentas (neste caso, o Firebug, um plugin do navegador Firefox), é possível aceder aos cabeçalhos HTTP trocados com o servidor. Acima, o navegador recebeu os seguintes cabeçalhos HTTP:
As linhas 7–8 são reconhecíveis como o cabeçalho HTTP enviado pelo script Python. As linhas anteriores foram geradas pelo servidor web Apache.
12.1.3. Um cliente programado
Vamos agora escrever um script que atuará como cliente para o serviço web anterior. Utilizaremos as funcionalidades do módulo httplib, que facilita a escrita de clientes HTTP.
Notas:
- Linha 3: O módulo re é necessário para expressões regulares e o módulo httplib para funções de cliente HTTP;
- linha 9: É criada uma ligação HTTP utilizando a porta 80 no HOST definido na linha 6;
- linha 11: o log permite visualizar os cabeçalhos HTTP da solicitação do cliente e da resposta do servidor;
- linha 13: a URL do serviço web é solicitada. Existem duas formas de a solicitar: utilizando um comando HTTP GET ou POST. A diferença entre os dois é explicada mais adiante. Aqui, será solicitada utilizando o comando HTTP GET;
- linha 15: a resposta do servidor é lida. A resposta completa é obtida aqui: cabeçalhos HTTP e o recurso solicitado pelo cliente. Na sua resposta, o servidor pode ter instruído o cliente a redirecionar. Neste caso, o cliente httplib executa automaticamente o redirecionamento. A resposta obtida é, portanto, aquela resultante do redirecionamento;
- linha 17: a resposta é composta pelos cabeçalhos HTTP e pelo documento solicitado pelo cliente. Para recuperar apenas os cabeçalhos HTTP, utilize [response].getHeaders(). Para recuperar o documento, utilize [response].read();
- Linha 19: Assim que a resposta do servidor web é obtida, a ligação ao mesmo é encerrada;
- Sabemos que o documento enviado pelo servidor é uma linha de texto no formato 15/06/11 14:56:36. Linhas 22–26: Utilizamos uma expressão regular para extrair os vários elementos desta linha.
12.1.4. Resultados
Notas:
- linha 1: os cabeçalhos HTTP enviados pelo cliente ao servidor web;
- Linhas 2–6: os cabeçalhos HTTP na resposta do servidor web;
- Linha 8: o documento enviado pelo servidor;
- Linha 11: o resultado do seu processamento;
12.2. O servidor recupera os parâmetros enviados pelo cliente
No protocolo HTTP, um cliente dispõe de dois métodos para passar parâmetros ao servidor web:
- solicita o URL do serviço no formulário
GET url?param1=val1¶m2=val2¶m3=val3… HTTP/1.0
onde os valores válidos devem primeiro ser codificados para que determinados caracteres reservados sejam substituídos pelos seus valores hexadecimais.
- solicita a URL do serviço na forma
depois, entre os cabeçalhos HTTP enviados ao servidor, inclui o seguinte cabeçalho:
O resto dos cabeçalhos enviados pelo cliente terminam com uma linha em branco. Pode então enviar os seus dados na forma
onde os valores devem, tal como no método GET, ser codificados previamente. O número de caracteres enviados para o servidor deve ser N, sendo N o valor declarado no cabeçalho:
12.2.1. O serviço web
O serviço web a seguir recebe três parâmetros do seu cliente: last_name, first_name e age. Ele recupera esses parâmetros a partir de uma estrutura semelhante a um dicionário chamada cgi.FieldStorage, fornecida pelo módulo cgi. O valor vali de um parâmetro parami é obtido usando vali = cgi.FieldStorage().getlist("parami"). Isto devolve uma matriz de:
- 0 elementos se o parâmetro parami não estiver presente na solicitação do cliente;
- 1 elemento se o parâmetro parami estiver presente uma vez na solicitação do cliente;
- n elementos se o parâmetro parami estiver presente n vezes na solicitação do cliente.
Depois de os parâmetros terem sido recuperados, o script envia-os de volta ao cliente.
É possível realizar um teste utilizando um navegador web:
![]() |
Em [1], a URL do serviço web. Repare na presença dos três parâmetros last_name, first_name, age. Em [2], a resposta do serviço web.
12.2.2. O cliente GET
Notas:
- linhas 8–10: os valores dos 3 parâmetros enviados ao serviço web;
- linha 13: estes devem ser codificados. Isto é feito utilizando o método urlencode do módulo urllib. Este módulo é importado na linha 3. O método recebe um dicionário {param1:val1, param2:val2, ...} como parâmetro;
- linha 15: numa solicitação GET (linha 21), o cliente deve colocar os parâmetros codificados no final da URL do serviço web;
- As linhas seguintes já foram abordadas.
12.2.3. Os resultados
Notas:
- linha 2: repare na codificação dos parâmetros (last_name, first_name, age);
- linha 8: a resposta do serviço web.
12.2.4. O cliente POST
O cliente POST é semelhante ao cliente GET, exceto que os parâmetros codificados já não fazem parte do URL de destino. São passados como o terceiro argumento do pedido POST (linha 19).
12.2.5. Resultados
Notas:
- Nota na linha 2: o método POST utilizado pelo cliente para enviar os parâmetros codificados:
- O cabeçalho HTTP Content-Length indica o número de caracteres que serão enviados para o serviço web;
- este cabeçalho HTTP é seguido por uma linha em branco que indica o fim dos cabeçalhos HTTP;
- depois, são enviados os 39 caracteres dos parâmetros codificados.
- Linha 8: a resposta do serviço web.
12.3. Recuperação de variáveis de ambiente de um serviço web
12.3.1. O serviço web
O script CGI em Python é executado num ambiente de sistema que possui atributos. Os seus atributos e os respetivos valores estão disponíveis no dicionário os.environ.
Notas:
- Linha 3: É necessário importar o módulo os para aceder às variáveis «system».
Se executar o script acima diretamente (ou seja, como um script de consola em vez de um script CGI), verá os seguintes resultados na consola:
Num navegador da Web (onde o script CGI é executado), obtêm-se os seguintes resultados:
![]() |
Note que, dependendo do contexto de execução, o ambiente obtido não é o mesmo.
12.3.2. O cliente programado
12.3.3. Resultados
Note que o cliente programado não recebe exatamente a mesma resposta que o navegador web. Isto deve-se ao facto de o navegador ter enviado informações ao servidor web que este utilizou para gerar a sua resposta. Neste caso, o cliente programado não enviou quaisquer informações sobre si próprio.




