Ambiente virtual
Um ambiente virtual é uma área isolada de seu computador onde pacotes específicos são instalados para o uso, sem o problema de conflitarem com outras versões instaladas. Com isso cada projeto pode ter suas próprias dependências, diferentes das possíveis dependências em outros projetos. Até mesmo versões diferentes do python podem ser usadas. Um projeto do Python pode usar diversos pacotes e módulos, sendo que alguns deles podem não estar na biblioteca padrão. Vários ambientes podem ser criados e gerenciados separadamente, sem limite na quantidade, pois são apenas diretórios contendo scripts. Esses ambientes podem ser criados usando as ferramentas no comando de linha venv, virtualenv ou pyenv. Nos concentraremos aqui na ferramenta venv.
Criando ambientes virtuais
Na construção de um aplicativo uma versão específica de uma biblioteca, ou até do próprio Python, pode ser necessária. Para isso a linguagem oferece a possibilidade de se criar ambientes virtuais: um ambiente independente armazenado em uma árvore de diretórios própria contendo a instalação do Python e pacotes em versão específica.
O módulo venv
é usado para criar e gerenciar ambientes virtuais. Ele seleciona e organiza a versão do Python e dos módulos usados no projeto.
Para criar um ambiente virtual você deve decidir em que diretório ele deve ser abrigado. Depois execute o módulo venv
como um script, no prompt de comando, informando o caminho do diretório. Uma boa prática é criar uma pasta oculta .venv
na sua pasta raiz ou pasta de projetos para abrigar todos os seus ambientes virtuais. No exemplo criaremos a pasta ~/Projetos/.venv/aprendendo
:
$ python3 -m venv ~/Projetos/.venv/aprendendo
Dentro da pasta aprendendo é criada uma estrutura de pastas contendo uma cópia do interpretador e alguns arquivos de configuração, mostrada na figura 1.
Essas pastas tem o conteúdo:
- bin: arquivos que interagem com o ambiente virtual
- include: cabeçalhos C que compilam os pacotes Python
- lib: uma cópia da versão do Python junto com uma pasta site-packages onde cada dependência está instalada
Parte desses arquivos são links simbólicos (ou symlinks) que apontam para as corretas versões das ferramentas do python.
Na pasta bin ficam os scripts de ativação usados para definir o ambiente para uso. Depois de criado o ambiente pode ser ativado por meio do comando activate
.
activate.bat
é um arquivo de lote que indica a posição do executável que aciona o ambiente. No Linux source
é um comando interno da shell que lê e executa o arquivo indicado.# No windows: $ ~\Projetos\.venv\aprendendo\Scripts\activate.bat # No Linux (bash shell) $ source ~/Projetos/.venv/aprendendo/bin/activate
Ao ser carregado um novo ambiente o prompt de comando muda para indicar qual ambiente está em uso. Nesse prompt carregamos o Python (no meu caso 3.8.8 Anaconda), importamos a biblioteca sys
e verificamos os caminhos em uso.
(aprendendo) $ python Python 3.8.8 (default, Apr 13 2021, 19:58:26) [GCC 7.3.0] :: Anaconda, Inc. on linux Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> sys.path ['', '/home/usr/.anaconda3/lib/python38.zip', '/home/usr/.anaconda3/lib/python3.8', '/home/usr/.anaconda3/lib/python3.8/lib-dynload', '/home/usr/Projetos/.venv/aprendendo/lib/python3.8/site-packages'] >>> sys.prefix '/home/usr/Projetos/.venv/aprendendo'
Esse ambiente está isolado do meio externo. Por exemplo, no meu caso o pandas foi instalado junto com o Anaconda. No entanto ele não pode ser apontado por um código rodando no ambiente (aprendendo).
>>> import pandas Traceback (most recent call last): File "", line 1, in ModuleNotFoundError: No module named 'pandas'
Para sair do ambiente reservado usamos deactivate no terminal.
(aprendendo) (base) [guilherme@gui ~]$ deactivate (base) [guilherme@gui ~]$ python Python 3.8.8 (default, Apr 13 2021, 19:58:26) [GCC 7.3.0] :: Anaconda, Inc. on linux Type "help", "copyright", "credits" or "license" for more information. >>> import pandas
Como o pandas está instalado globalmente, nenhuma mensagem de erro é gerada e o módulo fica disponível para uso.
A ativação de um ambiente significa a especificação do local onde estão os executáveis e bibliotecas importadas. Para reativar o ambiente nos “deslocamos” até a pasta onde ele está instalado e executamos activate.
$ cd /home/usuario/Projetos/.venv/aprendendo $ source bin/activate # o prompt é alterado (aprendendo) $ python >>> import sys >>> sys.prefix '/home/guilherme/Projetos/.venv/aprendendo'
Pode ocorrer que existam mais de uma versão do Python instalada em seu computador. Para criar um ambiente com outra versão devemos executar o script do venv na versão que desejamos para o ambiente virtual. Por exemplo, para um ambiente com python 3.11 (supondo que ele esteja instalado nesse computador) devemos executar:
$ python3.11 -m venv ~/Projetos/.venv/VsCode $ source ~/Projetos/.venv/VsCode/bin/activate $ python >>> Python 3.11.0a7 (main, Apr 7 2022, 00:00:00) [GCC 11.2.1 20220127 (Red Hat 11.2.1-9)] on linux >>> Type "help", "copyright", "credits" or "license" for more information.
Nesse caso criamos um ambiente virtual no diretório ~/Projetos/.venv/VsCode.
Gerenciando ambientes virtuais com pip
Uma vez dentro do novo ambiente você pode instalar pacotes usando pip
que, por default, encontra e instala pacotes do Python Package Index. PIP é o gerenciador padrão de pacotes (ou bibliotecas) do Python, que acessa um reservatório de pacotes publicados no Python Package Index, ou PyPI. Em versões mais recentes ele vem instalado por default. Um pacote é um conjunto de arquivos que executam uma ou várias funções. Eles podem ser importados em um aplicativo para extender a funcionalidade do Python padrão. PIP funciona por meio de comandos de linha, digitados no prompt do sistema operacional.
A sintaxe de venv
é descrita abaixo. Aqui usamos a notação [parâmetros opcionais], o pipe | para indicar opções (um ou | outro). Apenas ENV_DIR
é obrigatório e posicional.
venv | [-h] [–system-site-packages] [–symlinks | –copies] [–clear] [–upgrade] [–without-pip] [–prompt PROMPT] [–upgrade-deps] ENV_DIR [ENV_DIR …] |
Cria o ambiente virtual em um ou mais diretórios especificados. |
ENV_DIR | Diretório onde criar o ambiente virtual, |
-h, –help | exibe (o presente) texto de ajuda, |
–system-site-packages | Dá acesso ao ambiente virtual para a pasta site-packages do sistema. |
–symlinks | Tenta usar symlinks no lugar de cópias, quando os symlinks não são default na plataforma. |
–copies | Tenta usar cópias no lugar de symlinks, mesmo que symlinks sejam o default na plataforma. |
–clear | Apaga o conteúdo do diretório de ambiente, se existe, antes da criação do ambiente. |
–upgrade | Atualiza o diretório de ambiente, caso o python do ambiente tenha sido atualizado. |
–without-pip | Interrompe a instalação ou atualização via pip nesse ambiente. (Por default o pip é acionado). |
–prompt PROMPT | Estabelece um prefixo alternativa para o prompt desse ambiente. |
–upgrade-deps | Atualiza as dependências do pip setuptools para o última versão disponível em PyPI. |
Depois que o ambiente é criado você deve ativá-lo com o script source pasta/do/ambiente/bin/activate
.
Instalação de PIP
Você pode verificar a presença do pip
(ou conferir a versão) com pip --version
, no prompt de comando.
$ pip --version pip 22.0.3 from /home/usuario/Projetos/.venv/aprendendo/lib/python3.8/site-packages/pip (python 3.8)
O output do comando mostra a versão do pip e do python sendo usados no ambiente virtual instalado na pasta /home/usuario/Projetos/.venv/aprendendo
.
Alternativamente, é possivel encontrar onde está instalado o pip
:
# no Windows C:\> where pip3 # no Linux $ which pip ~/.anaconda3/bin/pip $ which pip3 ~/.anaconda3/bin/pip3
Caso o pip não esteja instalado, isso pode ser feito de duas formas: ensurepip
e get-pip.py
.
No prompt do terminal de seu sistema (que representaremos por $
, comentários por #
) digite:
$ python -m ensurepip # ou $ python -m ensurepip --upgrade
A chave -m garante que pip
seja executado como um módulo. Na segunda forma se garante que apenas versões mais novas que atual (se presente) seja instalada. Nenhuma ação será executa se já existe a instalação, ou se está em sua versão mais atual, no segundo caso. pip será instalado globalmente ou no ambiente virtual, se esse estiver ativo.
Outra alternativa é baixar o script get-pip.py e executá-lo com a primeiro linha no código. A segunda linha é uma forma de atualizá-lo.
# instalar pip $ python get-pip.py # fazer atualização de pip $ python -m pip install --upgrade pip
Instalando módulos com o PIP
O uso geral de pip é o seguinte:
# no linux/Mac $ python -m pip <argumentos> # ou $ pip <argumentos> # no windows $ py -m pip <argumentos>
Para instalar um módulo com o PIP executamos pip com o argumento install e o nome do módulo. Vários módulos podem ser instalados com uma única linha.
$ python -m pip install # ou $ pip install # por exemplo, para instalar o Flask $ pip install Flask # vários módulos $ python -m pip install ...
Para controlar qual é a versão a ser instalado usamos:
python -m pip install Modulo # instalar a última versão python -m pip install Modulo ==1.0.4 # instalar versão especificada python -m pip install 'Modulo >=1.0.4' # especificar a versão mínima
É possível passar para pip uma lista de requisitos para a exata reprodução de um ambiente.
# para gerar o arquivo relativa a um ambiente: $ python -m pip freeze > requirements.txt # para reproduzir a instalação: $ python -m pip install -r requirements.txt
O arquivo requirements.txt contém uma lista dos argumentos do pip install
. Essa lista pode ser gerada com freeze.
pip
pode ser usado para instalar pacotes de outros repositórios. Por exemplo, se você deseja instalar o pacote rptree
disponível em TestPyPI package index
, ou no GitHub.
# no TestPyPI python -m pip install -i https://test.pypi.org/simple/ rptree # no GitHub python -m pip install git+https://github.com/realpython/rptree
Observação: pode ocorrer que em seu computador o python 3 esteja instalado com o nome python3
.
<h2=”idm”>Listando e desinstalando módulos
Módulos instalados podem ser vistos com o argumento list. A lista obtida reflete a instalação do Flask e suas dependências. Uma lista com pacotes desatualizados é obtida com a chave list –outdated.
$ python -m pip list Package Version ------------ ------- click 8.0.3 Flask 2.0.2 itsdangerous 2.0.1 Jinja2 3.0.3 MarkupSafe 2.0.1 pip 22.0.3 setuptools 49.2.1 Werkzeug 2.0.2 # listar apenas pacotes desatualizados $ python -m pip list --outdated Package Version Latest Type ---------- ------- ------ ----- setuptools 49.2.1 60.8.1 wheel
Pode ocorrer que você deseje usar outro pacote e queira remover o antigo de seu computador. A desinstalação é feita com uninstall. pip desinstala pacotes com versões desatualizadas antes de fazer uma atualização para versão mais nova.
Um cuidado deve ser tomado: Quando um pacote é instalado é possível que ele possua dependências que são instaladas juntas com ele. Se você tem muitos pacotes instalados é possível que mais de um use a mesma dependência. Por isso é importante verificar se ele é dependência de outro ou se possui dependências. Para isso usamos python -m pip show <modulo>
.
$ python -m pip show Flask Name: Flask Version: 2.0.2 Summary: A simple framework for building complex web applications. Home-page: https://palletsprojects.com/p/flask Author: Armin Ronacher Author-email: armin.ronacher@active-4.com License: BSD-3-Clause Location: /home/guilherme/.anaconda3/lib/python3.8/site-packages Requires: itsdangerous, Jinja2, click, Werkzeug Required-by:
Vemos no output que Flask
possui as dependências (Requires: )itsdangerous
, Jinja2
, click
e Werkzeug
. Por outro lado ele não é exigido por nenhum outro modulo (Required-by:) portanto pode ser seguramente desinstalado. Para isso usamos uninstall.
$ python -m pip uninstall Flask
O mesmo procedimento deve ser usado com as dependências, caso você queira apagá-las.
Busca por pacotes
pip pode fazer buscas por um pacote com o comando:
python -m pip search "query"
A pesquisa retorna uma lista de pacotes com uma breve descrição de cada um.
Importante: pip search deixou de funcionar em dezembro de 2020. Um substituto para esse comando é poetry (que deve ser instalado em seu sistema). Por exemplo, uma busca por pacotes com “pandas” no nome: (o output está truncado).
$ poetry search "pandas" pandas (1.4.0) Powerful data structures for data analysis, time series, and statistics pandas3 (0.0.1) Boto3 extension to help facilitate data science workflows with S3 and Pandas pandas-alchemy (0.0.2) SQL based, pandas compatible DataFrame & Series
Poetry é similar ao npm do JavaScript, gerenciando pacotes e auxiliando na criação de distribuições de aplicativos e bibliotecas, além da inserção no PyPI. Outro pacote é o Pipenv que gerencia pacotes e controla ambientes virtuais. Real Python: Pipenv Guide.
Estrutura de um projeto Python
O Python é bastante flexível na questão de estrutura de pastas para um projeto. No entanto algumas sugestões foram dadas para um desenho ótimo para um projeto. Aqui eu sigo as sugestões de Lucas Tonin.
Vamos denominar nosso projeto de meu_projeto. Se estamos usando, como é recomendado, um ambiente virtual podemos criá-lo com python3 -m venv ~/Projetos/.venv/meu_projeto, que já estabelece uma estrutura mínima de pastas. Vamos por hora ignorar as pastas relativas ao ambiente virtual.
Para definir uma terminologia chamamos de projeto python tudo aquilo que estará no diretório base, que em nosso caso é ~/Projetos/.venv/meu_projeto
. Todos os arquivos relacionados ao desenvolvimento, teste e arquivos auxiliares ficam nesse diretório. Chamamos de pacote (package) ao conteúdo de um subdiretório dentro do projeto com o mesmo nome. O pacote contém o código-fonte do aplicativo. Ele isola o código fonte de todos os outros arquivos. Depois de pronto a instalaçao do projeto inclui apenas os arquivos contidos nesse diretório, ignorando código fonte e testes.
Arquivo __init__.py: O pacote deve necessariamente conter pelo menos um arquivo como o nome __init__.py
. A presença desse informa ao python que esse diretório é um pacote. __init__.py
é executado automaticamente quando esse pacote é carregado e deve conter as inicializações para o aplicativo. Duas coisas importantes podem ser aí incluídas: (a) uma variável ROOT_DIR com o caminho absoluto do atual pacote, onde estiver no momento; (b) as configurações de logger, quando existir.
from os.path import dirname, abspath ROOT_DIR = dirname(abspath(__file__)) # inicialização de logs
Um arquivo de documentação, README.md
: geralmente esses arquivos são escritos em MARKDOWN. Ele deve conter uma descrição de seu projeto para outros usuários de seu código, ou para você mesmo no caso de retomar após um tempo esse trabalho, além de instruções de instalações. Um exmplo simples:
Um aplicativo simples para a importação de arquivos *csv* e exportação para banco de dados SQL.
## Instalação
Para instalar execute `pip install /caminho/meu_projeto`
Usando setup.py: o arquivo setup.py
contém informações sobre configurações do pacate a ser instalado. No mínimo ele deve conter:
import setuptools setuptools.setup(name='meu_projeto', packages=['meu_projeto'])
que informa o nome do projeto e do pacote. O parâmetro packages informa ao pip que apenas esse diretório será instalado.
Para projetos maiores e mais complexos, que envolvem muitas dependências, é útil acrescentar um arquivo requirements.txt Este arquivo lista os pacotes necessários para o projeto, que não fazem parte da biblioteca padrão. Com ele o pip pode baixar e instalar automaticamente todas as dependências, se não o encontrar já instalado. Por exemplo, se o projeto depende do numpy (um pacote para computação científica) a arquivo deverá conter pelo menos a linha
numpy==1.18.2
O arquivo setup.py deve ser modificado para que essa informação seja usada.
# setp.py import setuptools with open('requirements.txt', 'r') as f: install_requires = f.read().splitlines() setuptools.setup(name='meu_projeto', packages=['meu_projeto'], install_requires=install_requires)
Um arquivo LICENCE, que descreve a licença sob a qual você está distribuindo seu projeto, pode ficar no diretório base, onde pode ser facilmente encontrado. Finalmente, uma pasta separa para os testes usados para testar a correção do código.
O projeto fica portanto com a seguinte estrutura mostrada na figura.
Usando Jupyter Notebook em ambiente virtual
Anaconda é uma plataforma de distribuição de Python e R muito usada para a ciência de dados e aprendizado de máquina. Ele simplifica a instalação de pacotes como pandas, NumPy, SciPy, e pode ser usada com diversas outras linguagens. Conda é o gerenciador padrão de pacotes do Anaconda, multiplataforma e agnóstico à linguagem e que pode ser usado para instalar pacote de terceiros. O Anaconda Navigator, instalado junto com o Anaconda, é uma interface gráfica que permite o gerenciamento de pacotes coda, com busca, instalação, atualização e desinstalação, execução dos aplicativos incluidos na Anaconda Cloud ou outro repositório Anaconda local. Todo esse sitema está disponível para Windows, macOS e Linux.
O Anaconda Cloud é um serviço de nuvem que abriga pacotes, notebooks e ambientes Python para variadas situações e casos, incluindo pacotes conda e PyPI públicos e privados. Ele permite o uploud de pacotes de usuário e notebooks, sem a necessidade de um login ou conta na nuvem.
Jupyter Notebook é uma ambiente interativo de interface do usuário da Web onde se pode rodar código nas linguagens instaladas, criar documentos de notebook contendo texto (em Markdown), imagens e vídeos. Esses documentos podem ser partilhados e publicados na nuvem, onde podem ser alterados e executados por outros usuários.
O Jupyter Notebook faz um gerenciamento de ambiente próprio. Mas tambem podemos criar um ambiente virtual específico para ele. Isso é bastante útil pois esse ambiente é usualmente dedicado à computação científica e aplicações com grandes volumes de dados, exigindo bibliotecas específicas. Para isso criamos um ambiente virtual, que chamaremos de jupyter
. Depois ativamos o ambiente e instalamos o Jupyter Notebook dentro desse ambiente.
# criamos o ambiente virtual $ python3 -m venv ~/Projetos/.venv/jupyter_venv # ativamos esse ambiente $ cd /home/usuario/Projetos/.venv/jupyter_venv $ source bin/activate # instala o Jupyter Notebook no ambiente (jupyter) $ ipython kernel install --user --name=jupyter_venv
Para usar o ambiente virtual abra o jupyter
e selecione o kernel no menu kernel | change kernel. A opção para o ambiente jupyter_venv deve estar disponível, como mostra a figura, como uma das opções de kernel a usar.
Para desinstalar o ambiente fazemos:
$ jupyter-kernelspec uninstall jupyter_venv
Gerenciador conda
Para quem está trabalhando com a distribuição Python Anaconda (site) é mais interessante usar o gerenciador conda
, que além de gerenciar pacotes e suas dependências controle também ambioentes virtuais. Ele pode ser usado com Python, R, Ruby, Lua, Scala, Java, JavaScript, C/ C++, FORTRAN e outras.
Com o conda
você pode pesquisar por pacotes, instalar os pacotes desejados ou construir um pacote do usuário com build
(conda-build
deve ser instalado).
A versão de conda
pode ser verificada, e atualizada se necessário. Essa atualização pode incluir atualização de outros pacotes e remoção de pacotes não usados.
# verificar versão $ conda --version conda 4.10.3 # informações mais detalhadas podem ser obtidas $ conda info active environment : base active env location : /home/guilherme/.anaconda3 # -----(outpup truncado)----- # atualizar versão $ conda update conda # se existir versão mais recente Proceed ([y]/n)? y
A pesquisa e instalação de pacotes é feita com search
e install
. A construção (build) de pacotes é feitas com build
.
# pesquisar $ conda search scipy # instalação $ conda install scipy # o novo pacote deve estar na lista $ conda list # construir um pacote $ conda build meu_projeto
Versões podem ser especificadas, inclusive com o uso de operadores lógicos.
conda install numpy=1.11 #(instala versão especificada) conda install numpy==1.11 #(idem) conda install "numpy>1.11" #(versão superior a 1.11) conda install "numpy=1.11.1|1.11.3" #(versão 1.11.1 ou 1.11.3) conda install "numpy>=1.8,<2" #(versão maior ou igual a 1.8 mas inferior a 2)
A barra |
é o operador OR
: “pacote=1.1|1.3” significa 1.1 ou 1.3.
A vírgula ,
é o operador AND
: “pacote=1.1,1.3” significa ambos 1.1 e 1.3.
O igual =
é o operador fuzzy: “pacote=1.11” pode ser “1.11”, “1.11.1”, , “1.11.8”, etc.
O duplo igual ==
é o operador exato: “pacote==1.11” pode ser “1.11”, “1.11.0”, , “1.11.0.0”, etc.
Gerenciamento de ambientes com conda
Um novo ambiente, que chamaremos de cientifico
pode ser criado, e simultanemanete instalado nele o pacote pandas
. Caso um versão do Python diferente da versão default do Anaconda instalado usamos a declaração conda create --name nome_ambiente python=n
, onde n é a versão desejada.
# criar um ambiente com um pacote $ conda create --name cientifico pandas Proceed ([y]/n)? y # ativar o ambiente $ conda activate cientifico # para verificar a versão do python em uso $ python --version Python 3.8.8 # para criar ambiente coom outra versão do python conda create --name cientifico python=3.9
Uma lista de todos os ambientes disponíveis pode ser vista com info --envs
. As pastas listadas dependem do local onde os ambientes foram criados.
$ conda info --envs conda environments: base /home/username/Anaconda3 cientifico * /home/username/Anaconda3/envs/cientifico
O ambiente ativo aparece com um asterisco *.
Um canal conda é um local na rede onde pacotes estão armazenados. Por default Conda busca em uma lista de canais e baixa arquivos de Repo Anaconda, onde alguns pacotes podem ser prorietários. Outros repositórios podem ser apontados com o conda, por exemplo o Conda Forge, uma organização parte do GitHub que contém um grande número de pacotes gratuitos. O parâmetro --override-channels
é usado para que os canais default (gravados em .condarc
) sejam ignorados.
# para apontar para o conda-forge $ conda install scipy --channel conda-forge # múltilpos repositórios podem ser apontados $ conda install scipy --channel conda-forge --channel bioconda # argumentos que aparecem na frente são pesquisados primeiro # para pesquisar em repositório local, ignorando os defaults $ conda search scipy --channel file:/caminho/local-channel --override-channels
Para instalar um pacote presente no conda-forge
também é possível fazer:
$ conda config --add channels conda-forge $ conda config --set channel_priority strict $ conda install "nome-do-pacote"
Muito mais é possível com o Conda
: consulte as instruções em Conda Docs.
comando | descrição |
---|---|
clean | Remove pacotes e caches não utilizados. |
compare | Compara pacotes entre ambientes conda. |
config | Modifica os valores de configuração em .condarc. (feito após a configuração do comando git). Grava arquivo .condarc do usuário |
create | Cria um ambiente conda a partir de uma lista de pacotes especificados. |
help | Exibe uma lista de comandos conda disponíveis e suas ajudas. |
info | Exibe informações sobre a instalação atual do conda. |
init | Inicializa o conda para interação do shell. [Experimental] |
install | Instala uma lista de pacotes em um ambiente conda especificado. |
list | Lista pacotes vinculados em um ambiente conda. |
package | Utilitário de pacote conda de baixo nível. (EXPERIMENTAL) |
remove | Remove uma lista de pacotes de um ambiente conda especificado. |
uninst | Alias para remove. |
run | Execute executável em um ambiente conda. [Experimental] |
search | Pesquisa pacotes e exibe informações associadas. |
update | Atualiza pacotes conda para a versão compatível mais recente. |
upgrade | Alias para update. |
comando | descrição |
---|---|
-h, –help | Mostra ajuda, |
-V, –version | Mostra versão. |
Bibliografia
- Conda: Conda Docs
- PIP: Pip documentation, v.22.0.3,
- PIP: Python Package Index,
- Python Docs: Virtual Environments and Packages,
- Real Python: Virtual Environments, a Primer,
- Real Python: Using Python’s pip to Manage Your Projects’ Dependencies,
- Toni, Lucas: Optimal Python Project Structure