Artigo original: https://www.freecodecamp.org/news/manage-multiple-python-versions-and-virtual-environments-venv-pyenv-pyvenv-a29fb00c296f/

Inclusão de janeiro de 2019: se você está voltando a esta publicação após fazer o upgrade para o macOS Mojave, confira esta issue no github para ver uma solução para o problema comum do pyenv, "zlib not available".

Antes de começarmos, vamos analisar rapidamente os termos usados no título:

  • Diversas versões do Python: instalações diferentes do Python na mesma máquina, 2.7 e 3.4, por exemplo.
  • Ambientes virtuais (texto em inglês): ambientes independentes e isolados que têm uma versão específica do Python e pacotes específicos de projeto instalados internamente, sem afetar outros projetos.

Aqui, examinaremos três ferramentas diferentes para se trabalhar com isso e veremos quando você poderá precisar de cada uma dessas soluções. Vamos analisar os casos de uso para:

  • venv/pyvenv
  • pyenv
  • pyenv-virtualenv

Se estiver usando uma única versão do Python - por exemplo, a versão 3.3 ou posterior - e se quiser gerenciar ambientes virtuais diferentes, você somente precisa do venv.

Se quiser usar diversas versões do Python nas versões 3.3 ou posteriores, com ou sem ambientes virtuais, siga lendo sobre o pyenv.

Se também quiser trabalhar com o Python 2, o pyenv-virtualenv é uma ferramenta que deve ser levada em consideração.

venv

A partir da versão do Python 3.3, o pacote venv já está incluído na instalação. Ele é ideal para a criação de ambientes virtuais leves.

Até o Python 3.6, um script chamado pyvenv também era incluído como um wrapper ao redor do venv, but mas ele agora foi abandonado. Ele foi completamente removido na versão Python 3.8. A mesma funcionalidade está disponível ao usar o venv. Toda a documentação existente deve ser atualizada. Para os interessados, vocês poderão ler sobre os motivos de não se utilizar mais o pyvenv (texto em inglês).

O venv é usado para criar um novo ambiente por meio de um comando de terminal:

$ python3 -m venv nome-do-diretorio-a-ser-criado

ativado com:

$ source name-given/bin/activate

e desativado simplesmente com:

$ deactivate

Se precisar remover o ambiente completamente após desativá-lo, basta executar:

$ rm -r nome-dado-ao-diretorio

Por padrão, o ambiente que ele cria será na versão atual do Python que você utiliza. Se estiver escrevendo documentação e quiser a segurança adicional de que a versão correta do Python está sendo usada pelo seu leitor, você pode especificar o número de versão maior e menor no comando, assim:

$ python3.6 -m venv exemplo-na-versao-tres-ponto-seis

Se o leitor estiver usando uma versão diferente da 3.6, o comando não será bem-sucedido e indicará isso na mensagem de erro. No entanto, qualquer versão de patch (como a 3.6.4, por exemplo) funcionará.

Quando o ambiente está ativo, todos os pacotes podem ser instalados nele por meio do pip normalmente. Por padrão, o ambiente recém-criado não incluirá pacotes já instalados na máquina. O próprio pip não estará necessariamente instalado na máquina. Recomenda-se, primeiro, atualizar o pip para sua versão mais recente usando o comando pip install --upgrade pip.

Os projetos normalmente terão um arquivo requirements.txt especificando suas dependências. Isso permite que o comando de atalho pip install -r requirements.txt instale rapidamente todos os pacotes no ambiente virtual recém-criado. Esses pacotes existirão apenas no ambiente virtual. Eles não estarão disponíveis quando ele for desativado, mas persistirão dentro dele quando de sua reativação.

Se não precisar usar versões adicionais do Python, isso é tudo o que você precisa para criar ambientes virtuais isolados e específicos de cada projeto.

pyenv

Se você deseja usar diversas versões do Python em uma única máquina, o pyenv é a ferramenta normalmente usada para instalar diferentes versões e alternar entre elas. Não se deve confundi-lo com o script mencionado anteriormente e já abandonado, o pyvenv. Ele não vem com o Python e deve ser instalado separadamente.

A documentação do pyenv inclui uma descrição detalhada de seu funcionamento (texto em inglês). Assim, aqui, veremos simplesmente como utilizá-lo.

Primeiro, precisamos instalá-lo. Se estiver usando o Mac OS X, é possível fazer isso usando o Homebrew. Caso contrário, há outras opções de instalação (texto em inglês).

$ brew update
$ brew install pyenv

Em seguida, adicione o seguinte ao final de seus scripts do shell para permitir que o pyenv alterne entre versões automaticamente para você:

eval "$(pyenv init -)"

Para fazer isso, abra seu script do shell que está em uso no momento (texto em inglês), usando o $ ~/.zshrc, $ ~/.bashrc ou o $ ~/.bash_profile e copie e cole nele a linha acima.

Ao executar pyenv versions, você verá quais versões do Python estão instaladas atualmente, com um * ao lado da que está em uso no momento. pyenv version mostra isso diretamente, enquanto python --version pode ser usado para confirmar isso.

Para instalar uma versão adicional, por exemplo, a 3.4.0, basta usar pyenv install 3.4.0.

pyenv procura em quatro lugares para decidir qual versão do Python deve utilizar, em ordem de prioridade:

  1. A variável de ambiente PYENV_VERSION (se estiver especificada). Você pode usar o comando pyenv shell para definir essa variável de ambiente em sua sessão de shell atual.
  2. O arquivo específico de cada aplicação chamado .python-version no diretório atual (se estiver presente). Você pode modificar o arquivo .python-version do diretório atual com o comando pyenv local.
  3. O primeiro arquivo .python-version encontrado (se houver) ao pesquisar cada diretório pai, até chegar à raiz (root, em inglês) de seu sistema de arquivos.
  4. O arquivo de versão global. Você pode modificar esse arquivo usando o comando pyenv global. Se o arquivo de versão global não estiver presente, o pyenv assumirá que você quer usar o Python "do sistema" (em outras palavras, a versão que for executada se pyenv não estiver no seu PATH).

Ao configurar um novo projeto que usará o Python 3.6.4, pyenv local 3.6.4 seria executado em seu diretório raiz. Isso configuraria a versão e criaria um arquivo .python-version, de modo que outras máquinas colaboradoras do projeto o recebessem.

A descrição completa dos comandos do pyenv (texto em inglês) é uma boa sugestão de se ter em seus favoritos.

pyenv e venv

Ao trabalhar com o Python 3.3 e versões posteriores, já sabemos como instalar versões do Python e alternar entre elas, bem como o modo de criar novos ambientes virtuais.

Como exemplo, vamos supor que estamos configurando um projeto que tenha de usar o Python 3.4.

Primeiro, podemos configurar nossa versão local usando pyenv local 3.4.0.

Se, então, executarmos python3 -m venv projeto-de-exemplo, um novo ambiente virtual será configurado em projeto-de-exemplo, usando nosso Python 3.4.0 ativado no local.

Fazemos a ativação usando source projeto-de-exemplo/bin/activate e podemos começar a trabalhar.

Em seguida, podemos, como opção, documentar que um colaborador deve usar python3.4 -m venv <nome>. Isso quer dizer que, mesmo que um colaborador não esteja usando o pyenv, o comando python3.4 causaria um erro se a versão dele do Python não for a mesma versão maior e menor (3 e 4, respectivamente), conforme pretendíamos.

Como alternativa, podemos escolher simplesmente especificar que a versão 3.4.0 deve ser usada, e instruir python3 -m venv <nome>. Se acreditarmos que qualquer versão acima da 3.4 for aceitável, podemos escolher usar python3 em vez de python3.4. Assim, se o colaborador estiver usando a versão 3.6, ele não receberia um erro. Essa é uma decisão que depende de cada projeto.

pyenv-virtualenv

O pyenv pode ser usado para instalar tanto versões do Python 2 como do Python 3. Porém, como vimos, o venv é limitado a versões do Python superiores a 3.3.

O pyenv-virtualenv é uma ferramenta para criar ambientes virtuais integrados com o pyenv, funcionando para todas as versões do Python. Ainda é recomendado usar o venv oficial do Python quando for possível. Porém, se, por exemplo, você estiver criando um ambiente virtual com base na versão 2.7.13, essa ferramenta complementa o pyenv.

Ela também funciona bem com os ambientes conda de Anaconda e Miniconda se os estiver usando. Uma ferramenta chamada virtualenv também existe. Não é tratada aqui, mas há um link para ela ao final.

Após instalar o pyenv, é possível instalá-la no Mac usando o Homebrew (ou suas alternativas - texto em inglês) assim:

$ brew install pyenv-virtualenv

Em seguida, em seu .zshrc, .bashrc ou .bash_profile (dependendo do shell que você usa), adicione o seguinte ao final do arquivo:

eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"

Isso permitirá que o pyenv ative e desative ambientes automaticamente ao mover os diretórios.

Para criar um novo ambiente virtual, use:

$ pyenv virtualenv <version> <nome-a-ser-dado>

// por exemplo

$ pyenv virtualenv 2.7.10 my-virtual-env-2.7.10

Os ambientes existentes podem ser criados com:

$ pyenv virtualenvs

Ative-os/desative-os com:

$ pyenv activate <nome>
$ pyenv deactivate

No momento em que escrevo este artigo, ao usar activate, o aviso prompt changing will be removed from future release será exibido. Isso é esperado (texto em inglês) e se refere apenas ao (nome-do-env) que é exibido em seu shell, não ao uso do próprio comando activate.

Instalar os requisitos funciona da forma descrita na parte sobre o venv. Diferentemente do venv, um comando rm -r não é necessário para remover um ambiente, pois existe um comando uninstall (texto em inglês).

Conclusões

Com essas três ferramentas, conseguimos colaborar em qualquer projeto, não importando a versão do Python ou as dependências exigidas. Também sabemos como documentar as instruções de configuração para outros que utilizem qualquer projeto em que trabalharmos.

Podemos ver, também, o motivo por trás do uso de cada conjunto, já que nem todos os desenvolvedores necessitarão dos três.

Espero que o artigo tenha lhe auxiliado e que seja uma referência útil em combinação com a documentação, cujos links estão abaixo.

Obrigado pela leitura!

Aqui temos outras questões que já tratei em artigos (em inglês):

Recursos (em inglês)