sábado, 27 de novembro de 2010

Flask

Flask Há diversos frameworks em Python para Web, Django, Zope, web2py, Pyramid e TurboGears e Pylons.

Venho aqui para falar de um microframework chamado Flask.

Simples, flexível e poderoso, é capaz de manter desde o projeto mais simples até CMS no estilo Django ou grandes aplicações como em Pylons.

A instalação é também extremamente simples, já que se encontra no PyPI:
bash$ easy_install Flask


Como exemplo vou mostrar uma aplicação ao estilo Flask, registrando as URLs com decorador route, mas para aplicações mais complexas sugiro criar um arquivo url_rules.py que importe o objeto aplicação e use o método add_url_rule em vez do decorador.

Nossa aplicação simples exibirá o conteúdo dos arquivos em /proc/ dos sistemas Unix (por falta de ideia melhor).

Podemos começar importanto os recursos necessários:
from flask import Flask, make_response


  • Flask: classe da aplicação
  • make_response: função capaz de criar um objeto de resposta HTTP


Para a leitura dos arquivos e diretórios vamos precisar do módulo os:
import os


Vamos agora criar duas funções, uma que retorne a listagem de arquivos para um diretório e outra que retorne o conteúdo de um arquivo:
def list_dir(path):
filelist = os.listdir(path)
filelist.sort()
return '\n'.join(filelist)


def read_file(path):
data = 'NO DATA'
with open(path, 'r') as fd:
data = fd.read()
return data


Agora é possível criar a aplicação:
app = Flask(__name__)
app.debug = True


Podemos então criar uma função que receba o caminho do arquivo/diretório a ser lido e retorne para o navegador.

Caso seja necessário editar os cabeçalhos ou lidar com qualquer peculiaridade do objeto de resposta HTTP, é possível instanciá-lo manualmente. Caso contrário, retornar uma simples string já faz com que ela seja entendida como o conteúdo do objeto.

Se uma tupla for retornada, o primeiro valor será o conteúdo e o segundo o status de retorno.

Sabendo disso, podemos definir a função:
@app.route('/<path:filename>/')
def read_proc(filename):
real_path = os.path.join('/proc', filename)
data = 'NO DATA'

try:
if os.path.isfile(real_path):
data = read_file(real_path)

elif os.path.isdir(real_path):
data = list_dir(real_path)

else:
return 'NOT FOUND', 404

# Criando HTTP response apenas para editar headers
response = make_response(data)
response.headers['Content-Type'] = 'text/plain'
return response

except IOError:
# Você não pode ler este arquivo/diretório!
return 'BAD REQUEST', 400


A rota indica que o argumento filename receberá como parâmetro toda a URL passada (path: indica uma string com /).

Para a raiz da aplicação, poderíamos usar as funções redirect e url_for, por exemplo:
@app.route('/')
def index():
return redirect(url_for('read_proc', filename='cpuinfo'))


O que redirecionaria para a URL referente à função read_proc, passando 'cpuinfo' como parâmetro, mas faz mais sentido retornar o resultado da função:
@app.route('/')
def index():
return read_proc('')


Agora só falta colocar a aplicação para rodar:
if __name__ == '__main__':
app.run(host='0.0.0.0')


Execute o script e acesse no navegador: http://localhost:5000/ – você verá a listagem do diretório /proc/.

Acesse no navegador: http://localhost:5000/cpuinfo/ e você verá o conteúdo do arquivo /proc/cpuinfo.

Pretendo em uma próxima oportunidade demonstrar com construir uma estrutura mais complexa usando um arquivo com roteamente em vez de decorador.

Para mais diversão, leia a documentação e fascine-se também com a quantidade de vezes que a expressão «you don’t have to deal with that» se repete.

[]’s
Cacilhας, La Batalema