Ambiente Isolado para Python com virtualenv

Postado por Osvaldo Santana

Boa parte do meu dia-a-dia de desenvolvedor é gasto em proramando em Python. Gosto de estar sempre atualizado com o que há de novo para essa linguagem e para isso saio instalando tudo o que aparece para para experimentar. Além de Python o Linux também faz parte da minha vida e uso ele quase 100% do meu tempo (em vias de mudar para o OS X).

A plataforma Python, de uns tempos pra cá, vêm padronizando os arquivos Eggs para distribuição de aplicações e bibliotecas. Em conjunto com o PyPI (Python Package Index) e o utilitário easy_install (que é parte do framework setuptools) é possível instalar componentes Python com apenas um comando.

A facilidade para instalar esses pacotes é enorme mas removê-los é chato porque envolve a edição de alguns arquivos texto, e ter permissão de escrita no diretório de bibliotecas do Python (permissão que também é necessária para a instalar o pacote).

Cada pacote instalado acrescenta uma entrada ao sys.path do Python fazendo com que o tempo para importar um módulo aumente um pouco mais (cada uma dessas entradas é consultada em busca do módulo e se você der uma olhada na saída do strace verá que a procura por um módulo envolve vários passos).

O Linux que eu uso (Ubuntu) precisa ter um ambiente Python estável, já que grande parte de suas aplicações roda em cima dessa linguagem, ou seja, danificar esse ambiente pode atrapalhar todo o funcionamento do sistema.

Isso tudo junto com o fato de que adoro experimentar as novidades do mundo Python faziam com que meu Python ficasse totalmente poluído com versões bleeding edge de bibliotecas que muitas vezes são incompatíveis com as versões “oficialmente suportadas” pelo pessoal que faz o Ubuntu.

Seria necessário um jeito fácil de se criar ambientes isolados do Python usando como base a própria instalação do sistema para que eu pudesse fazer esses testes e experiências sem danificá-lo. Não ficar replicando cópias de Python pela máquina também seria interessante.

E então surge a solução…

Parece engraçado mas no mesmo dia que perdi horas “arrumando” o Python em meu computador eu li no blog do Ian Bicking que ele tinha desenvolvido um programinha que fazia exatamente o que eu precisava: o virtualenv.

O uso do virtualenv é extremamente simples e direto. Basta instalar, executar e ativar.

Instalação

Se você está usando Ubuntu ou Debian:

sudo apt-get install python-setuptools
sudo easy_install virtualenv

Se não está:

wget http://peak.telecommunity.com/dist/ez_setup.py
sudo python ez_setup.py

Criando o ambiente

Para criar um ambiente basta executar o virtualenv e passar como parâmetro o nome do diretório onde tal ambiente será instalado:

virtualenv meu_python

Esse comando irá criar um diretório chamado meu_python com os diretórios:

  • bin - executável do interpretador, o script easy_install e o arquivo activate que será usado para “ativar” o ambiente. Quando o ambiente está “ativo” os executáveis dos aplicativos Python são instalados aqui também.
  • lib - a árvore com links simbólicos e/ou cópias de todos os módulos e bibliotecas do Python. Quando esse ambiente está “ativo” os módulos e pacotes serão sempre instalados dentro desse diretório.
  • include - dentro desse diretório estão os links simbólicos para todos os headers do Python que são necessários para se compilar extensões escritas em C para ele.

Ativando o ambiente para usar

Para usar esse ambiente recém-criado é necessário ativá-lo. para isso basta executar o seguinte comando:

source meu_python/bin/activate

Esse comando irá adicionar o diretório meu_python/bin no PATH da sua sessão e mudar o prompt para que você possa distinguir visualmente quando este ambiente está ativo.

Atenção: O virtualenv não cria o link simbólico python -> python2.5, portanto, se precisar dele você terá que criá-lo à mão com o seguinte comando

(cd meu_python/bin; ln -s python2.5 python; hash -r)

Depois disso é só sair instalando as coisas sem a menor preocupação.

PS. Eu não testei o virtualenv no Windows nem no Mac OS X mas no site do projeto é possível notar que tem gente usando ele também nessas duas plataformas, portanto, eu acho que ele também funcione corretamente nelas.


O sistema de testes dos meus sonhos

Postado por Osvaldo Santana

O uso de testes no desenvolvimento de software já vem me acompanhando desde que trabalhei com Smalltalk na Objective Solutions. O sistema de testes que eles tinham lá chegava muito próximo do que eu idealizo para um sistema de testes.

Recentemente eu li o livro Test-Driven Development do Kent Beck e resolvi experimentar TDD de forma radical em um projeto pessoal em que estou desenvolvendo em Python. O meu sentimento geral sobre o uso de TDD é a de que estou programando num ritmo bem mais lento do que costumo ter mas com a certeza absoluta de que estou seguindo pelo caminho correto.

Como os detalhes de implementação desse projeto não estão muito claros em minha cabeça o uso de TDD está se mostrando ideal, mas não recomendo para o desenvolvimento de uma aplicação na qual você já tenha uma boa idéia de como implementar pois ela realmente ‘desacelera’ o seu ritmo. Mas atenção: estou desaconselhando o uso de TDD e não a criação de testes! Nos projetos onde é possível desenvolver testes é fundamental fazê-lo.

Mas voltando ao assunto deste post eu adoraria ver uma ferramenta para Python com as seguintes funcionalidades:

  1. Suportar testes escritos com xUnit (unittest) e doctests.
  2. Vir junto com framework xUnit mais poderoso que o unittest padrão do Python. O py.test tem umas idéias legais. Juntar outras bibliotecas auxiliares, tais como o mocker, também seria legal.
  3. Ter um sistema de discovery automático para testes (ex. nose).
  4. Ter uma interface texto para uso em servidores de testes.
  5. Ter uma interface gráfica para uso do desenvolvedor.
  6. Suportar execução distribuída de testes. Ainda não preciso disso mas estou prevendo que precisarei no futuro.
  7. Integração com algum software de lint (ex. pylint).
  8. Integração com sistemas de teste de cobertura (ex. coverage).
  9. Emitir relatório sobre a qualidade do código (baseado na análise do lint), da cobertura dos testes, do tempo de execução dos testes e, em caso de falha, o traceback do erro.
  10. Permitir a execução do pdb caso algum teste falhe.
  11. Integração com o mecanismo de persistência de objetos (ORM, OODBMS, …) para permitir a criação de savepoints (aka subtransactions) para testes que precisam construir cenários com muitos objetos. Criando esses savepoints um teste poderia fazer um rollback parcial dos objetos criados/alterados pelo teste executado anteriormente. Eu usei essa integração na Objective e garanto que era muito útil além de diminuir o tempo para execução dos testes de forma colossal.

Mockup da Tela
Modelo da interface gráfica dessa aplicação*.

Esse é o sistema dos meus sonhos e acredito que, conforme o desenvolvimento do meu projeto avance, eu acabe com algo muito parecido nas mãos. Mas se alguém quiser começar antes eu prometo que usarei e, caso me sobre tempo, ajudarei no desenvolvimento :)

Quem sabe um dia esse carinha trabalhe integrado a um SCM, ao reviewboard e a um sistema de issue tracker… mas chega de viagem, hora de voltar ao trabalho.

* Note que ainda está faltando uma Treeview para selecionar o módulo cujo código fonte será exibido.