2019-04-01
Vinicius Assef

Entendendo virtualenv

Virtualenv é uma daquelas coisas simples e poderosas, que quando a gente entende a utilidade, gostaria de vê-la também em outras linguagens.

Vamos, então, entender os virtualenvs.

O que é um virtualenv?

Tecnicamente, um virtualenv é apenas um diretório. É muito simples e, ao mesmo tempo, genial.

Virtualenv quer dizer virtual environment (ambiente virtual). Certo, mas a que ambiente estamos nos referindo? Ao ambiente Python.

Em outras palavras, é o lugar que o interpretador Python vai buscar os pacotes (bibliotecas) externos para poder usá-los.

O que são pacotes externos?

Python é dividido em duas partes: a linguagem e a biblioteca.

A linguagem é composta pelos comandos, por exemplo, for, if, return, etc.

A biblioteca é formada pelo que conhecemos como "as pilhas incluídas". São os pacotes embutidos, os builtins. Dito de outra forma, os pacotes embutidos fazem parte da Standard Library (biblioteca padrão) do Python, a stdlib. Simplificando, eles já vêm com o Python. datetime (que manipula data e hora), csv (para ler arquivos csv), math (com funções matemáticas) são alguns exemplos de pacotes builtin.

Além das "pilhas incluída", Python permite que os programadores adicionem novos pacotes à biblioteca e sejam usados como se fossem parte da biblioteca padrão. Esses são os pacotes externos.

Em geral eles simplificam ou melhoram alguma solução que as "pilhas incluídas" do Python não fazem muito bem. Bons exemplos de pacotes externos são frameworks web (Django, Flask, etc.) ou pacotes usados em ciência de dados (pandas, scipy, etc). Python já vem com as "baterias incluídas", mas sempre é possível melhorar o que já é bom.

Como os pacotes externos não vêm com o Python, precisamos instalá-los.

Eu entendi o que são pacotes, mas qual é a finalidade de um virtualenv?

A única finalidade de um virtualenv é separar o ambiente de seus projetos Python, para que um não interfira nos outros. Vamos deixar isso mais prático.

O benefício mais imediato de um virtualenv é permitir a você, usar versões diferentes de um pacote externo, sem que uma versão entre em conflito com a outra.

Qual a real utilidade disso?

Imagine que você tem 2 projetos usando Django.

O projeto A, usa Django versão 1.11 e o projeto B usa Django versão 2.0. Como fazer para ter os dois projetos funcionando no mesmo computador, já que usam versões diferentes do mesmo pacote?

Resposta: Usando virtualenvs.

Por que eu não posso instalar duas versões de um mesmo package sem virtualenv?

Porque a última versão que você instalar vai sobrepor a que já estava instalada. Nesse caso, é possível que um dos seus projetos pare de funcionar.

OK, como faço para ter meus virtualenvs?

Você vai precisar criar um virtualenv para cada projeto e ativar quando for usá-lo.

Nesse artigo, vamos criar o virtualenv apenas para o Projeto A, do exemplo acima. O do Projeto B, você pode criar como dever de casa.

Mas, antes, vamos combinar que seu Projeto A está localizado no diretório /home/eu/sistemas/projeto_a/.

Para criar o virtualenv:

$ python -m venv /home/eu/sistemas/projeto_a/.venv

Como eu mencionei no início desse artigo, o virtualenv é apenas um diretório comum. Se você for curioso, pode ver o conteúdo dele com o seguinte comando:

$ ls /home/eu/sistemas/projeto_a/.venv

Com isso, já temos o virtualenv criado para o Projeto A, mas ele ainda não serve para nada.

E agora, como faço para usar o virtualenv?

Você precisa ativá-lo com o seguinte comando:

$ source /home/eu/sistemas/projeto_a/.venv/bin/activate

A ativação de um virtualenv vale apenas para sessão atual do terminal. Ao fechar o terminal, o virtualenv é desativado.

Pra quê ativar o virtualenv?

Pra dizer ao Python em qual lugar ele deve procurar por um pacote quando você usar um comando import no seu programa.

E também para o pip saber em qual lugar ele deve instalar um pacote quando você usar pip install <nome_do_package>.

Então, com o virtualenv ativado, o pip instala o pacote nele e o Python encontra o que você instalou nele.

Como posso saber se o virtualenv está ativado?

Com o seguinte comando:

$ echo $VIRTUAL_ENV

A variável de ambiente $VIRTUAL_ENV tem o path do virtualenv ativo. Se o resultado for vazio, nenhum virtualenv está ativado no momento.

Observação: é provável que quando você ativar o virtualenv, o prompt do terminal passe a mostrar o nome do diretório dele entre parênteses (.venv, no nosso exemplo).

Meu virtualenv está ativado. Como faço para usá-lo?

Se você tem certeza que seu virtualenv está ativado, prossiga. Se ele ainda não está ativado, volte um pouco no texto e veja como ativá-lo.

Agora, vamos tentar usar um pacote que ainda não instalamos. Abra o interpretador Python, digitando:

$ python

Quando o prompt do Python aparecer, digite o seguinte:

>>> import django

Se você não instalou o Django antes no seu computador (e você realmente não deveria ter instalado fora do virtualenv), verá uma mensagem semelhante a:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'django'

Isso significa que, para usarmos o Django, precisamos instalá-lo. Vamos fazer isso agora.

Saia do interpretador Python (teclando CTRL+D) e digite, na linha de comando:

$ pip install django

Você verá várias mensagens dizendo que o Django e suas dependências estão sendo copiadas e instaladas.

Quando o comando terminar de processar, abra novamente o interpretador Python com:

$ python

No prompt do Python, digite:

>>> import django

Agora você não verá mais a mensagem de erro. Isso significa que o comando foi executado com sucesso. O Python encontrou o Django que instalamos há pouco.

Confira qual versão de Django foi instalada, digitando:

>>> django.__version__

Pronto. É assim que um virtualenv funciona. Só isso.

O que vimos até aqui já basta para você usar virtualenvs. Apenas lembre-se: ative o virtualenv antes de usá-lo.

Se você já estiver satisfeito, pode parar de ler o artigo aqui mesmo.

Mas se você quer saber mais detalhes sobre virtualenvs, vamos continuar.

Entendi tudo. Você pode resumir pra mim?

Posso.

Para criar um virtualenv:

$ python -m venv <path-do-virtualenv>

Para apagar um virtualenv:

$ rm -rf <path-do-virtualenv>

Para ativar um virtualenv:

$ source <path-do-virtualenv>/bin/activate

Agora use pip install para instalar pacotes e/ou desenvolva e use programas que usem os pacotes instalados.

Eu devo incluir o diretório do virtualenv no git?

Não. Inclua o nome dele no arquivo .gitignore para tirá-lo do git.

Como eu faço para apagar um virtualenv?

Basta desativar o virtualenv e deletar o diretório em que ele se encontra. No nosso exemplo:

$ rm -rf /home/eu/sistemas/projeto_a/.venv

Lembre de desativá-lo antes de apagar o diretório.

Eu preciso criar o virtualenv no diretório .venv?

Não. Essa é apenas uma convenção. Ao seguí-la, você deixa o virtualenv com um nome padrão e junto com seu projeto. Muita gente usa assim e algumas ferramentas usam a mesma convenção para ativar o virtualenv automaticamente quando você abre o projeto ou entra (cd) no diretório.

Mas seu virtualenv pode estar em qualquer diretório do seu computador. Só não pode estar no mesmo diretório dos fontes do seu projeto.

Por exemplo, se seus fontes estiverem em /user/eu/sistemas/projeto_a/, você não pode criar o virtualenv no mesmo lugar. Por isso criamos nosso virtualenv em um subdiretório dentro do projeto.

Para facilitar, posso criar meu virtualenv no mesmo diretório que meus programas fonte, certo?

Não! De jeito nenhum!

Leia a resposta à pergunta anterior.

Eu tenho dois projetos que usam a mesma versão de uma biblioteca. Posso usar um virtualenv só?

Pode, mas não deveria.

Imagine que daqui a algum tempo você resolva usar um recurso novo da biblioteca que um deles usa, em uma versão mais recente, mas no outro projeto, não. Você terá problemas.

Por princípio, crie um virtualenv para cada projeto e mantenha-os separados. Você não vai se arrepender.

Por que o comando pip dá erro quando tento instalar algum pacote, se eu não usar virtualenv?

Porque quando você não tem um virtualenv ativado, o pip vai tentar instalar o pacote em um diretório global, para todo o seu computador.

Geralmente esse diretório é protegido e você só consegue fazer isso usando sudo, o que eu não recomendo.

Esse comportamento funciona também como proteção, para você perceber que precisa ativar o virtualenv antes de instalar um pacote para seu projeto.

Mas veja, o ideal para manter a independência dos projetos Python é você sempre usar um virtualenv e nunca instalar um pacote globalmente.

Aonde foi parar o comando virtualenv?

Se você estiver usando Python 3.4 ou mais recente, esqueça-o; não precisamos mais dele. Agora usamos python -m venv.