Você está aqui: Página Inicial Documentação Tutoriais Tutorial CherryPy

Tutorial CherryPy

Ações do documento

Aviso: Esta é uma visão de impressão com todas as páginas do tutorial em uma página. A versão paginada está disponível aqui, se você preferir esta.

Tradução de http://docs.cherrypy.org/cherrypy-tutorial

Introdução

Introdução ao CherryPy

O que é o CherryPy?

CherryPy é um framework de desenvolvimento web pythônico e orientado à objetos. Ele fornece a base sobre a qual complexas aplicações web podem ser escritas, com pouco ou nenhum conhecimento sobre os protocolos inferiores. CherryPy permite que desenvolvedores construam aplicações web exatamente da mesma maneira que fariam para desenvolver qualquer outra aplicação orientada à objetos em Python, o que geralmente resulta em um código fonte menor desenvolvido em menos tempo.

CherryPy faz o melhor possível para não ficar entre o programador e o problema. Aplicações CherryPy normalmente são muito simples. Tudo isso funciona "direto de fábrica": o comportamento padrão foi feito permitir o uso sem configurações ou customizações excessivas. O servidor web embutido permite o uso de aplicações web em qualquer lugar que tiver Python instalado: resumindo, CherryPy é tão pythônico quanto pode ser.

O que o CherryPy NÃO é?

Como um framework de aplicações web, CherryPy faz todo o necessário para permitir que código Python seja executado quando algum recurso (ou URL) é requisitado pelo usuário. Porém, ele não é uma linguagem de templates como PHP. CherryPy pode trabalhar com várias linguagens de template, incluindo Cheetah, CherryTemplate e muitas outras. Mas perceba que, embora sejam muito úteis para determinadas tarefas, linguagens de template não são estritamente necessárias, e código Python puro pode ser usado para gerar páginas web.

CherryPy inclui um servidor web leve embutido, capaz o suficiente para suportar cargas medianas. A estimativa é que CherryPy pode suportar 500 requisições/segundo em uma configuração razoável (testado em Janeiro/2005); isso pode ser traduzido, a grosso modo, em um throughput de 15 Mbps. Porém, CherryPy não é um Apache: se por qualquer razão você precisar de um servidor web de nível corporativo, você pode rodar CherryPy e Apache juntos.

Sobre o que é esse tutorial?

Esse tutorial cobre os passos básicos para um iniciante "captar" o jeito único que o CherryPy usa para desenvolver aplicações web. Após seguir esse tutorial, o programador vai ser capaz de entender como aplicações CherryPy funcionam, e também como implementar sozinho aplicações simples e poderosas. É assumido algum conhecimento sobre a linguagem Python; ninguém precisa ser um especialista para trabalhar com CherryPy, mas um bom entendimento sobre as bases da orientação à objetos é fortemente recomendado.

Conhecimento básico necessário

É assumido que o desenvolvedor possui:

  • Algum conhecimento sobre a linguagem de programação Python
  • Alguma experiência com orientação à objetos.
  • Algum conhecimento de HTML, necessário para construir páginas web.

Aprendendo Python

Como dito acima, esse não é um guia de Python. Existem muitos bons recursos para quem quer aprender Python (para citar os melhores: "Python course in Bioinformatics", "A Byte of Python" e "Dive into Python"). O site oficial da linguagem Python tem muitos recursos interessantes, incluindo um tutorial excelente.

NT: O wiki PythonBrasil é uma excelente referência em português.

Sua primeira aplicação CherryPy

Desenvolvimento de uma aplicação simples e apresentação dos conceitos mais básicos

Sua primeira aplicação CherryPy

A aplicação padrão "Hello world!" fica com menos de 10 linhas de código quando escrita usando CherryPy.


import cherrypy

class HelloWorld:
def index(self):
return "Hello world!"
index.exposed = True

cherrypy.root = HelloWorld()
cherrypy.server.start()

Assumiremos que você já tem CherryPy e Python instalados. Copie esse arquivo e salve-o localmente como hello.py; depois, inicie um prompt de comando:

python hello.py

Aponte seu navegador favorito para http://localhost:8080 e você deverá ver "Hello world!" na tela.

Como funciona?

Vamos dar uma olahda no hello.py:

  • A expressão import cherrypy importa o módulo principal do CherryPy. Isso é tudo o que você precisa para ter o CherryPy na sua aplicação.
  • Nós declaramos uma classe chamada HelloWorld. Uma instância dessa classe é o objeto que seja publicado pelo CherryPy. Ele contém um único método chamado "index", o qual será chamado quando a URL base do site for requisitada (por exemplo, http:/localhost/). Esse método retorna o conteúdo da página web; nesse caso, a string "Hello World!".
  • A expressão index.exposed = True é um passo necessário para dizer ao CherrPy que o método index() deve ser exposto. Somente métodos expostos podem responder uma requisição. Esse recurso permite que o programador selecione que métodos de um objeto estarão acessíveis via web; métodos não-expostos não podem ser acessados.
  • A expressão cherrypy.root = HelloWorld() publica uma instância da classe "HelloWorld".
  • A chamada cherrypy.server.start() inicia o servidor web embutido. Esse servidor é executado até ser interrompido explicitamente, usando Ctrl+C ou via sinais (um simples "kill" em um Unix pode fazê-lo). Também é possível implementar o desligamento do servidor dentro da aplicação, mas isso está fora do escopo desse tutorial.

Quando a aplicação é executada, o servidor CherryPy é iniciado com a configuração padrão. Ele vai escutar em localhost na porta 8080. Esses padrões podem ser sobrescritos por um arquivo de configuração (mais sobre esse assunto depois).

Por fim, o servidor web recebe uma requisição para a URL http://localhost:8080. Ele procura pelo método que melhor se encaixa à requisição, iniciando por cherrypy.root (que é a instância de HelloWorld). Nesse caso particular, a base do site é automaticamente mapeada para o método index() (de maneira similar ao index.html que é a página inicial para servidores web convencionais). A classe "HelloWorld" define o método index() e o expõe. CherryPy chama cherrypy.root.index() e o resultado da chamada é enviado de volta ao navegador como conteúdo da página inicial do website. Todo o trabalho é feito automaticamente; o programador só precisa fornecer o conteúdo desejado como valor de retorno do método index().

Conceitos

Publicando objetos

Qualquer objeto que é inserido em cherrypy.root é publicado. Isso significa que o objeto se torna acessível pela rotina interna de mapeamento URL-objeto. Porém, isso não significa que o objeto em si é diretamente acessível via Web. Para isso acontecer, o objeto deve ser exposto.

Expondo objetos

CherryPy mapeia requisições para URLs para objetos e chama o método apropriado automaticamente. Esse método que pode ser chamado como resultado de requisições externas é dito que é exposto.

Objetos são expostos no CherryPy setando o atributo "exposed". Isso pode ser feito diretamente no objeto: objeto.exposed = True. Métodos podem ser expostos também usando um decorator especial:


import cherrypy

class HelloWorld:
@exposed
def index(self):
return "Hello world!"

cherrypy.root = HelloWorld()
cherrypy.server.start()

Por quê essa distinção??

A distinção entre objetos publicados e expostos pode parecer inútil à primeira vista. Por definição, todos os objetos são automaticamente publicados, então por quê nós temos que nos preocupar com objetos não-expostos?

A resposta é que, apesar de que somente objetos expostos possam ser acessados como resultado de uma requisição externa, existem algumas situações onde requisições podem ser re-mapeadas para qualquer objeto publicado, incluindo objetos não-expostos. Isso é um recurso avançado que vamos explicar depois. Agora tudo o que precisamos é entender os conceitos básicos.

Encontrado o objeto certo

Para o usuário, uma aplicação web é exatamente como um website com arquivos estáticos. O usuário digita (ou clica) em uma URL e chega à página desejada. Um servidor web convencional usa a URL para carregar um arquivo estático do sistema de arquivos. Por outro lado, o servidor de aplicações web não somente serve conteúdo de arquivos estáticos; ele também pode mapear a URL que ele recebe em algum objeto e chamá-lo. O resultado então é enviado de volta para o navegador do usuário, onde é renderizado como uma página web. O resultado é uma aplicação web dinâmica: para cada URL, um objeto única pode ser chamado e executado.

A chave para entender como executar uma nova aplicação web é entenendo como esse mapeamento ocorre. CherryPy usa um procedimento de mapeamento bastante singular. A base do site é o objeto cherrypy.root. Quando o objeto recebe uma URL, ele a separa pelos componentes do caminho (path), e começa a procurar dentro das classes até encontra o objeto que é mais adequado para aquela URL particularmente. Para cada componente ele tenta encontrar o objeto como mesmo nome, iniciando por cherrypy.root, e vai "descendo" para cada componente que encontra até não encontrar mais nada. Um exemplo explica melhor:


cherrypy.root.onepage = OnePage()
cherrypy.root.otherpage = OtherPage()

No exemplo acima, a URL http://localhost/onepage vai apontar para o primeiro objeto e a URL http://localhost/otherpage vai apontar para o segundo. Como é de se esperar, essa busca é feita automaticamente. Mas pode ser feito ainda mais com o mapeamento:


cherrypy.root.some = Page()
cherrypy.root.some.page = Page()

Nesse exemplo, a URL http://localhost/some/page vai ser mapeada para o objeto cherrypy.root.some.page. Se esse objeto está exposto (ou seu método index() está), ele vai ser chamado para aquela URL.

O método index()

O método index() tem uma regra especial no CherryPy. Como um arquivo index.html, ele é a página padrão para qualquer nó interno na árvore de objetos. O método index() é o único método que não suporta parâmetros posicionais.

O método index() só é chamado se a URL inteira é válida. Se a URL é parcialmente válida (em outras palavras, se o CherryPy não conseguiu encontrar um objeto correspondente à um componente da URL) o método não será chamado.

Recebendo dados de formulários e Configurando o CherryPy

Mostra detalhes sobre esses dois conceitos

Chamando outros métodos

CherryPy pode também chamar diretamente métodos dos objetos publicados se ele receber uma URL que seja diretamente mapeada para esses métodos. Por exemplo:


def foo():
return 'Foo!'
foo.exposed = True

cherrypy.root.foo = foo

No exemplo, cherrypy.root.foo contém uma função chamada foo. Quando o CherryPy recebe uma requisição para a URI /foo ele automaticamente chama a função foo(). Note que isso pode ser uma função simples, um método ou qualquer outro objeto executável ("callable").

Em alguns casos avançados pode haver um conflito quando o CherryPy tenta decidir que método aplicar à uma requisição. O método index() tem precedência, mas se o CherryPy encontra uma URL com o caminho todo válido e com o último objeto no caminho sendo executável (o que significa qualquer método, função ou objeto Python que suporte o método __call__); e por fim, se o objeto executável não conter ele mesmo um método index() válido, então o objeto em si vai ser executado. Essas regras são necessárias porque as próprias classes são executáveis em Python; executá-las produz uma nova instância. Pode parecer confuso, mas as regras são bem simples de serem usadas na prática.

Recebendo dados de formulários HTML

Qualquer método que é executado pelo CherryPy - seja index ou qualquer outro - pode receber dados de formulários HTML usando keyword arguments. Por exemplo, o formulário de login abaixo envia username (nome de usuário) e  password (senha) como argumentos usando o método POST:

<form action="doLogin" method="post">
<p>Username</p><br>
<input name="username" size="15" maxlength="40" type="text"><br>
<p>Password</p><br>
<input name="password" size="10" maxlength="40" type="password"><br>
<p><input value="Login" type="submit"></p><br>
<p><input value="Clear" type="reset"></p><br>
</form>
O código abaixo pode tratar essa URL:

class Root:
def doLogin(self, username=None, password=None):
# check the username & password
...
doLogin.exposed = True

cherrypy.root = Root()

Ambos os argumentos tiveram que ser declarados como keyword arguments. O valor padrão pode ser usado tanto para  prover um valor padrão para valores opcionais ou para prover um meio da aplicação saber se algum parâmetro da requisição está faltando.

CherryPy suporta ambos os métodos GET e POST para formulários. Argumentos são passados do mesmo jeito, independente do método utilizado pelo navegador web para mandar os dados para o servidor web.

O arquivo de configuração do CherryPy


O CherryPy usa um simples arquivo de configuração para customizar alguns aspectos do seu comportamento. O arquivo de configuração pode ser editado com qualquer editor de textos convencional (até mesmo o Bloco de Notas), e pode ser usado inclusive por "usuários comuns" (não-técnicos) para algumas customizações simples. Por exemplo:


[global]
server.socket_port = 8000
server.thread_pool = 10
session_filter.on = True
static_filter.root = "/home/site"

[/static]
static_filter.on = True
static_filter.dir = "static"

Muitos dos valores são auto-explicativos (por exemplo, server.socket_port, que habilita a mudança da porta padrão na qual o CherryPy "escuta" requisições); outras necessidades precisam de um entendimento maior sobre os mecanismos internos do CherryPy.

  • A opção server.thread_pool determina quantas threads o CherryPy vai usar para servir requisições.
  • A expressão static_filter.root especifica o diretório de onde os arquivos estáticos serão servidos.
  • A expressão [/static] especifica que o conteúdo estático vindo de /home/site/static/* é servido como /static/*
  • A expressão session_filter.on habilita o suporte à sessões. Sessões são necessárias para implementar aplicações web complexas com identificação de usuários, por exemplo.

O nome do arquivo de configuração pode ser passado como argumento para o método update(); os valores vão ser lidos exatamente antes do servidor iniciar:


cherrypy.config.update(file="myserver.conf")
cherrypy.server.start()

As configurações podem também ser definidas como código Python puro usando dicionários e passando-os  diretamente para cherrypy.config.update.

cherrypy.server.start

A definição de cherrypy.server.start() é:


def start(self, init_only=False, server_class=_missing):
"""
Main function. All it does is this:
- read/parse config file if any
- create response and request objects

- start HTTP server
"""

Para mudar a configuração da sua aplicação você pode passar um dicionário como keyword parameter para  cherrypy.config.update() como no exemplo abaixo:


cherrypy.config.update({
'global': {
'server.socket_port' : 8888,
'server.thread_pool' : 10 }})

Estrutura do CherryPy, Filters e Conclusão

Explicação básica sobre a estrutura básica do módulo do CherryPy, sobre os filters, e o fim do tutorial.

A estrutura do módulo cherrypy

Muitos dos recursos do CherryPy são disponíveis pelo módulo cherrypy. Ele contém muitos membros:

  • Como mencionado anteriormente, cherrypy.root é a árvore de objetos publicados; o objeto em cherrypy.root é a base da aplicação, e os objetos que ele contém formam a árvore de objetos da aplicação.
  • cherrypy.server  contém a API para controlar o servidor.
  • cherrypy.request contém toda a informação que vem com uma requisição HTTP depois que é parseada e analisada pelo CherryPy.
    • cherrypy.request.headers é um dicionário que contém as opções de cabeçalho que foram enviadas como parte da requisição.
    • cherrypy.session é um dicionário automaticamente gerado pelo CherryPy; ele pode ser usado para guardar dados na sessão em um cookie. Para isso funcionar você tem que habilitar as sessões setando session_filter.on como True na sua configuração.
  • cherrypy.response contém os dados usados para construir a resposta HTTP.
    • cherrypy.response.headers contém um dicionário com as opções do cabeçalho que serão enviados na resposta HTTP, antes do conteúdo ser enviado.
    • cherrypy.response.body contém o conteúdo da página web que será enviado como resposta.

Filters (Filtros)

O núcleo do CherryPy é extremamente limpo e leve. Ele contém somente os recursos necessários para suportar o protocolo HTTP e para executar o objeto certo para cada requisição. Recursos adicionais podem ser adicionados usando filters.

Um filter é um objeto que tem a chance de trabalhar em uma requisição assim que ela chega para a cadeia de processamento do CherryPy. Vários filtros são providos como parte da biblioteca padrão do CherryPy, disponível em cherrypy.lib.filter. Alguns exemplos são:

  • DecodingFilter: automaticamente trata os dados Unicode da requisição, convertendo as strings "cruas" enviadas pelo navegador para strings Python nativas.
  • EncodingFilter: automaticamente converte a resposta de strings Unicode nativas do Python para alguma outra codificação de caracteres (Latin-1 ou UTF-8, por exemplo).
  • GzipFilter: Compacta o conteúdo "on the fly", usando o formato gzip. Isso poupa bandwidth.
  • XmlRpcFilter: Implementa uma camada especial de adaptação para XML-RPC acima do CherryPy padrão. Essa camada traduz os dados da requisição e resposta (um processo chamado 'marshalling').

Filters provém muita flexibilidade. Diferentes filters podem ser aplicados para diferentes partes da aplicação, e a ordem dos filtros pode ser modificada. O programador pode escrever filters customizados para aplicações específicas, mudando o comportamento do CherryPy sem ter que modificar seus mecanismos internos.

A lista de filters para qualquer parte do site é configurada habilitanto-a no arquivo de configuração do servidor:


[/]
encoding_filter.on = True
gzip_filter.on = True

Nesse caso, a aplica~çao usa strings Unicode para o conteúdo que ela gera; a tradução para utf8 será feita automaticamente. Adicionalmente, todo o conteúdo será compactado com Gzip, poupando bandwidth.

Conclusão

Esse tutorial cobre apenas os recursos básicos do CherryPy, mas ele tenta apresentá-los de uma maneira que facilite o aprendizado. A distribuição do CherryPy vem com vários bons tutoriais; apesar disso, a melhor maneira de dominar o CherryPy é usá-lo para escrever suas próprias aplicações web. O servidor web embutido facilita não apenas os testes, mas também a distribuição de aplicações locais, ou até mesmo pequenos web sites. Teste-o e nos conte o que você fez com ele!


O conteúdo deste site está sob licença Creative Commons