Organizando o ambiente Python

ATUALIZADO: Adicionei algumas informações extras com problemas encontrados. Obrigado Capucho.

Olá,

Python é uma das linguagens mais conhecidas da atualidade e tem ficado mais popular ainda com o hype do mundo da Ciência de Dados e Inteligência Artificial com bibliotecas como Tensorflow, PyTorch, Pandas entre outros.

Porém, nem tudo são flores e as vezes cada projeto tem suas particulariedades na versão de Python e dependências. Então, é preciso ter formas de gerenciar todo esse caos.

Vou compartilhar aqui de forma rápida e simples como faço isso nos diferentes ambientes que uso, no meu caso, OSX no trabalho e em casa no Linux ou no WSL (Linux no Windows).

pyenv

Acho que já virou uma unanimidade na comunidade que é o uso do pyenv para gerenciar as versões de Python instaladas na sua máquina, ele vai além disso com alguns plugins mas no caso vamos usar apenas para isso.

Instalando

O processo é bem simples em ambos:

OSX

brew install pyenv

Após a instalação será exibido uma informação sobre configuração do ambiente shell para o pyenv ser configurado no seu PATH.

Linux

git clone https://github.com/pyenv/pyenv.git ~/.pyenv

Configurando o shell

Configurando o PATH:

 echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
 echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
 echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n  eval "$(pyenv init -)"\nfi' >> ~/.bash_profile

Neste caso estou assumindo o uso do Bash.

Utilizando

Após reiniciar a sua sessão do terminal com o pyenv configurado no seu PATH já podemos dar os primeiros comandos.

versions

pyenv versions

Esse comando vai listar todas as versões de Python no seu sistema reconhecida por ele. Por padrão, após a instalação vai aparecer apenas a do sistema operacional que já veio instalada. Além disso, vai ter uma indicação de qual é a versão atual configurada no seu PATH

Dica, se você usar apenas version ele retorna apenas o atual.

install

Obviamente essa é a utilizada para instalar outras versões e listar as disponíveis para instalação. Para listar todas as versões execute:

pyenv install -l

Segue o exemplo do meu ambiente atual:

$ pyenv versions
* system (set by /home/jvrmaia/.pyenv/version)
  2.7.15
  3.6.5
  anaconda3-5.1.0
  pypy3.5-6.0.0

Detalhes

O pyenv vai instalar o Python via fonte, ou seja, compilar e configurar. Então, será preciso antes instalar algumas dependências para que seja possível realizar a instalação com êxito. Segue o link da wiki com as instruções para isso baseado nos problemas mais comuns.

global

Esse comando vai permitir você escolher qual será sua versão padrão do Python, no meu caso vou alterar para ser Python 3:

$ pyenv global 3.6.5
$ pyenv versions
  system
  2.7.15
* 3.6.5 (set by /home/jvrmaia/.pyenv/version)
  anaconda3-5.1.0
  pypy3.5-6.0.0

local

Esse é utilizado para no caso de algum projeto seu não usar o seu padrão global, por exemplo, um legado na versão 2 ainda.

$ mkdir legado
$ cd legado/
$ pyenv local 2.7.15
$ cat .python-version 
2.7.15
$ python --version
Python 2.7.15

pip & pipenv

Agora chegou a vez de gerenciar os pacotes do Python instalados nos seus projetos. Por muito tempo o pip foi a solução junto com a virtualização de ambientes. Porém, recentemente foi criado o pipenv que resolveu de forma mais elegante, na minha opinião, esse problema e vem ganhando o uso na comunidade.

Primeiramente, é preciso instalar o pipenv:

pip install pipenv

Em caso de falhar a instalação do pipenv confira o locale do seu shell. Ele deve ter o seguinte retorno:

$ locale
LANG=en_US.UTF-8
LANGUAGE=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=en_US.UTF-8

Caso contrário, execute e configure no seu ~/.bash_profile:

export LC_ALL=en_US.UTF-8  
export LANG=en_US.UTF-8

Instalando os primeiros pacotes:

$ pipenv install django
Creating a virtualenv for this project…
Using /home/jvrmaia/.pyenv/versions/2.7.15/bin/python2.7 (2.7.15) to create virtualenv…
⠋Already using interpreter /home/jvrmaia/.pyenv/versions/2.7.15/bin/python2.7
New python executable in /home/jvrmaia/.local/share/virtualenvs/legado-LJtjGn3T/bin/python2.7
Also creating executable in /home/jvrmaia/.local/share/virtualenvs/legado-LJtjGn3T/bin/python
Installing setuptools, pip, wheel...done.

Virtualenv location: /home/jvrmaia/.local/share/virtualenvs/legado-LJtjGn3T
Creating a Pipfile for this project…
Installing django…
Collecting django
  Downloading https://files.pythonhosted.org/packages/25/4d/c8228419346a0e84aec202a43e181afc6572b861d38f8a0306dbce6abef0/Django-1.11.13-py2.py3-none-any.whl (6.9MB)
Collecting pytz (from django)
  Downloading https://files.pythonhosted.org/packages/dc/83/15f7833b70d3e067ca91467ca245bae0f6fe56ddc7451aa0dc5606b120f2/pytz-2018.4-py2.py3-none-any.whl (510kB)
Installing collected packages: pytz, django
Successfully installed django-1.11.13 pytz-2018.4

Adding django to Pipfile's [packages]…
Pipfile.lock not found, creating…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Updated Pipfile.lock (71a00b)!
Installing dependencies from Pipfile.lock (71a00b)…
An error occurred while installing django==2.0.5! Will try again.
  🐍   ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 2/2 — 00:00:00
Installing initially–failed dependencies…
Collecting django==2.0.5 ▉▉▉▉▉▉▉▉▉▉▉▉ 0/1 — 00:00:00

  Could not find a version that satisfies the requirement django==2.0.5 (from -r /tmp/pipenv-d6z9n5-requirements/pipenv-SpGVpO-requirement.txt (line 1)) (from versions: 1.1.3, 1.1.4, 1.2, 1.2.1, 1.2.2, 1.2.3, 1.2.4, 1.2.5, 1.2.6, 1.2.7, 1.3, 1.3.1, 1.3.2, 1.3.3, 1.3.4, 1.3.5, 1.3.6, 1.3.7, 1.4, 1.4.1, 1.4.2, 1.4.3, 1.4.4, 1.4.5, 1.4.6, 1.4.7, 1.4.8, 1.4.9, 1.4.10, 1.4.11, 1.4.12, 1.4.13, 1.4.14, 1.4.15, 1.4.16, 1.4.17, 1.4.18, 1.4.19, 1.4.20, 1.4.21, 1.4.22, 1.5, 1.5.1, 1.5.2, 1.5.3, 1.5.4, 1.5.5, 1.5.6, 1.5.7, 1.5.8, 1.5.9, 1.5.10, 1.5.11, 1.5.12, 1.6, 1.6.1, 1.6.2, 1.6.3, 1.6.4, 1.6.5, 1.6.6, 1.6.7, 1.6.8, 1.6.9, 1.6.10, 1.6.11, 1.7, 1.7.1, 1.7.2, 1.7.3, 1.7.4, 1.7.5, 1.7.6, 1.7.7, 1.7.8, 1.7.9, 1.7.10, 1.7.11, 1.8a1, 1.8b1, 1.8b2, 1.8rc1, 1.8, 1.8.1, 1.8.2, 1.8.3, 1.8.4, 1.8.5, 1.8.6, 1.8.7, 1.8.8, 1.8.9, 1.8.10, 1.8.11, 1.8.12, 1.8.13, 1.8.14, 1.8.15, 1.8.16, 1.8.17, 1.8.18, 1.8.19, 1.9a1, 1.9b1, 1.9rc1, 1.9rc2, 1.9, 1.9.1, 1.9.2, 1.9.3, 1.9.4, 1.9.5, 1.9.6, 1.9.7, 1.9.8, 1.9.9, 1.9.10, 1.9.11, 1.9.12, 1.9.13, 1.10a1, 1.10b1, 1.10rc1, 1.10, 1.10.1, 1.10.2, 1.10.3, 1.10.4, 1.10.5, 1.10.6, 1.10.7, 1.10.8, 1.11a1, 1.11b1, 1.11rc1, 1.11, 1.11.1, 1.11.2, 1.11.3, 1.11.4, 1.11.5, 1.11.6, 1.11.7, 1.11.8, 1.11.9, 1.11.10, 1.11.11, 1.11.12, 1.11.13)
No matching distribution found for django==2.0.5 (from -r /tmp/pipenv-d6z9n5-requirements/pipenv-SpGVpO-requirement.txt (line 1))

  ☤  ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 0/1 — 00:00:00
/home/jvrmaia/.pyenv/versions/2.7.15/lib/python2.7/site-packages/pipenv/_compat.py:86: ResourceWarning: Implicitly cleaning up <TemporaryDirectory '/tmp/pipenv-d6z9n5-requirements'>
  warnings.warn(warn_message, ResourceWarning)

Não se assuste com o tamanho, vamos ver o que foi gerado na pasta do projeto:

$ ls
Pipfile  Pipfile.lock
$ cat Pipfile
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[dev-packages]

[packages]
django = "*"

[requires]
python_version = "2.7"
$ cat Pipfile.lock 
{
    "_meta": {
        "hash": {
            "sha256": "d28375af9522538c8c98fdbeca3740125ef48d8b658b156c89e8efc80471a00b"
        },
        "pipfile-spec": 6,
        "requires": {
            "python_version": "2.7"
        },
        "sources": [
            {
                "name": "pypi",
                "url": "https://pypi.org/simple",
                "verify_ssl": true
            }
        ]
    },
    "default": {
        "django": {
            "hashes": [
                "sha256:26b34f4417aa38d895b6b5307177b51bc3f4d53179d8696a5c19dcb50582523c",
                "sha256:71d1a584bb4ad2b4f933d07d02c716755c1394feaac1ce61ce37843ac5401092"
            ],
            "index": "pypi",
            "version": "==2.0.5"
        },
        "pytz": {
            "hashes": [
                "sha256:65ae0c8101309c45772196b21b74c46b2e5d11b6275c45d251b150d5da334555",
                "sha256:c06425302f2cf668f1bba7a0a03f3c1d34d4ebeef2c72003da308b3947c7f749"
            ],
            "version": "==2018.4"
        }
    },
    "develop": {}
}

Agora, para utilizar o Django é preciso ativar o ambiente virtual criado pelo pipenv:

$ pipenv shell
Spawning environment shell (/bin/bash). Use 'exit' to leave.
$ . /home/jvrmaia/.local/share/virtualenvs/legado-LJtjGn3T/bin/activate
(legado-LJtjGn3T) $ django-admin

Type 'django-admin help <subcommand>' for help on a specific subcommand.

Available subcommands:

[django]
    check
    compilemessages
    createcachetable
    dbshell
    diffsettings
    dumpdata
    flush
    inspectdb
    loaddata
    makemessages
    makemigrations
    migrate
    runserver
    sendtestemail
    shell
    showmigrations
    sqlflush
    sqlmigrate
    sqlsequencereset
    squashmigrations
    startapp
    startproject
    test
    testserver
Note that only Django core commands are listed as settings are not properly configured (error: Requested setting INSTALLED_APPS, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.).

Então, como podemos ver hoje é bem simples organizar seus projetos Python e não sofrer mais com isso. Para saber mais sobre o pipenv veja aqui.

Author image
Vitória - ES, Brasil Website
Formado em Engenharia de Computação na UFES e trabalhando com desenvolvimento de software para o mercado desde 2012. Hoje estou focado na área de ciência de dados e negócios.