Python venv

Na aula pip: Instalando Pacotes, o Ubuntu recusou o pip install e sugeriu "crie um ambiente virtual". Lá você usou três comandos sem muita explicação. Nesta aula você vai entender o que é esse ambiente virtual (em inglês, virtual environment, abreviado venv), o que tem dentro dele, como ligar e desligar, e por que todo projeto Python sério tem o seu.

Você vai aprender
  • O que é um ambiente virtual e por que cada projeto tem o seu.
  • A criar um com python3 -m venv .venv e a ver o que tem dentro da pasta.
  • A ativar (source .venv/bin/activate), reconhecer o prompt (.venv) e desativar (deactivate).
  • A conferir qual Python está em uso: which python e sys.prefix.
  • A apagar e recriar o ambiente a partir do requirements.txt.
  • Os erros reais: ativar sem source, pasta errada, copiar o projeto com a .venv junto.
Esta é uma aula de terminal

Ambientes virtuais são criados e ativados no terminal do seu computador. As janelas de terminal mostram o que o Ubuntu 26.04 da Ana respondeu de verdade. O editor do guia (o "Experimente") roda o Python do navegador, que não tem ambientes virtuais; as caixas desta aula treinam a lógica com os arquivos do ambiente.


A ideia: uma caixa de ferramentas para cada trabalho

A Ana faz bolos para fora e também conserta bicicletas no fim de semana. Ela não guarda as formas de bolo junto com as chaves de boca: cada atividade tem a sua caixa, com as ferramentas certas. Se um dia ela trocar a batedeira, a caixa da bicicleta nem fica sabendo.

Com os programas Python é igual. A lojinha da Ana usa o requests na versão mais nova; a agenda, que ela escreveu no ano passado, só funciona com uma versão mais antiga. Se os dois projetos usassem o mesmo Python, com os mesmos pacotes, um deles ia quebrar. A solução é dar a cada projeto a sua caixa:

Sem ambiente virtualCom um ambiente virtual por projeto
Todos os programas dividem os mesmos pacotesCada projeto tem os pacotes dele, numa pasta dele
Uma versão de cada pacote no computador inteiroA lojinha com o requests 2.34.2, a agenda com o 2.32.3, ao mesmo tempo
No Ubuntu, o pip install nem funciona (PEP 668)O pip funciona, sem sudo
Difícil saber do que o projeto precisaO pip freeze do ambiente é a lista exata

Um ambiente virtual é só isso: uma pasta com um Python "particular" e um lugar para os pacotes daquele projeto. Nada é instalado no sistema, e apagar a pasta desfaz tudo.


1. Criando: python3 -m venv .venv

A Ana vai começar um projeto novo, as encomendas da padaria. Primeiro a pasta do projeto, depois o ambiente dentro dela:

$ mkdir padaria
$ cd padaria
$ python3 -m venv .venv
$ ls -a
.
..
.venv
python3
O Python que vai servir de base para o ambiente (o do sistema, o 3.14).
-m venv
"Rode o módulo venv": ele vem com o Python e sabe criar ambientes.
.venv
O nome da pasta do ambiente. Pode ser qualquer nome, mas .venv é o costume: os editores de código (como o VS Code) procuram por ele, e o ponto na frente deixa a pasta "escondida" no ls comum (por isso o -a, de "all", "todos").

O comando não imprime nada: no terminal, silêncio quer dizer que deu certo. Leva um ou dois segundos, porque ele também instala um pip novinho lá dentro.

O que tem dentro da .venv

$ ls -a .venv
.
..
.gitignore
bin
include
lib
lib64
pyvenv.cfg
ItemO que é
bin/Os programas do ambiente: python, pip e o script activate (de "binários")
lib/python3.14/site-packages/Onde o pip do ambiente instala os pacotes
include/, lib64Detalhes internos; você não mexe neles
pyvenv.cfgA "ficha" do ambiente: de qual Python ele saiu
.gitignoreUm aviso para o git ignorar a pasta inteira (o ambiente não vai para o repositório)
$ cat .venv/pyvenv.cfg
home = /usr/bin
include-system-site-packages = false
version = 3.14.4
executable = /usr/bin/python3.14
command = /usr/bin/python3 -m venv /home/ana/padaria/.venv
$ cat .venv/.gitignore
# Created by venv; see https://docs.python.org/3/library/venv.html
*
home = /usr/bin
A pasta do Python original.
include-system-site-packages = false
"Incluir os pacotes do sistema? Não." O ambiente começa limpo e não enxerga os pacotes instalados pelo apt.
version = 3.14.4
A versão do Python do ambiente.
command = …
O comando que criou o ambiente, com o caminho completo da pasta. Guarde isso: o ambiente sabe onde foi criado.
*
No .gitignore, o asterisco quer dizer "ignore tudo nesta pasta".

E a pasta bin:

$ ls -l .venv/bin
total 36
-rw-r--r-- 1 ana ana 9031 Oct 18 11:48 Activate.ps1
-rw-r--r-- 1 ana ana 2158 Oct 18 11:48 activate
-rw-r--r-- 1 ana ana  914 Oct 18 11:48 activate.csh
-rw-r--r-- 1 ana ana 2185 Oct 18 11:48 activate.fish
-rwxrwxr-x 1 ana ana  240 Oct 18 11:48 pip
-rwxrwxr-x 1 ana ana  240 Oct 18 11:48 pip3
-rwxrwxr-x 1 ana ana  240 Oct 18 11:48 pip3.14
lrwxrwxrwx 1 ana ana    7 Oct 18 11:48 python -> python3
lrwxrwxrwx 1 ana ana   16 Oct 18 11:48 python3 -> /usr/bin/python3
lrwxrwxrwx 1 ana ana    7 Oct 18 11:48 python3.14 -> python3
lrwxrwxrwx 1 ana ana    7 Oct 18 11:48 𝜋thon -> python3
activate
O script que liga o ambiente no bash (o terminal do Ubuntu). Os outros (.csh, .fish, .ps1) são para outros terminais, como o PowerShell do Windows.
pip, pip3, pip3.14
Três nomes para o mesmo pip, o do ambiente.
python3 -> /usr/bin/python3
A seta indica um atalho (link simbólico): o Python do ambiente não é uma cópia inteira, é um atalho para o Python do sistema. O que muda é onde ele procura os pacotes.
python -> python3
Dentro do ambiente existe o comando python, sem o 3. Fora dele, no Ubuntu, não existe.
𝜋thon
Uma brincadeira do Python 3.14 (o "pi" de 3,14…): mais um atalho, com a letra grega π. Funciona, mas ninguém usa no dia a dia.

2. Ativando: source .venv/bin/activate

Criar o ambiente não basta: o terminal continua usando o Python do sistema. Veja:

$ which python3
/usr/bin/python3
$ python3 -c "import sys; print(sys.prefix)"
/usr

which ("qual") mostra qual programa roda quando você digita um nome. E sys.prefix é a pasta "de casa" do Python que está rodando (o módulo sys tem aula própria: Os Módulos os e sys). Os dois apontam para o sistema. Agora a Ana ativa o ambiente:

$ source .venv/bin/activate
(.venv) ana@notebook:~/padaria$ which python3
/home/ana/padaria/.venv/bin/python3
(.venv) ana@notebook:~/padaria$ which python
/home/ana/padaria/.venv/bin/python
(.venv) ana@notebook:~/padaria$ python -c "import sys; print(sys.prefix)"
/home/ana/padaria/.venv
(.venv) ana@notebook:~/padaria$ pip list
Package Version
------- -------
pip     25.1.1
source
"Leia e execute este arquivo aqui, neste terminal". É obrigatório: o activate muda o terminal em que você está, e só o source deixa ele fazer isso.
.venv/bin/activate
O caminho do script, a partir da pasta do projeto.
(.venv)
O prompt ganhou o nome do ambiente na frente. É o sinal de que ele está ativo: olhe para ele sempre antes de rodar pip install.
which python3
Agora aponta para dentro da .venv.
pip list
Só o pip: o ambiente é novo e limpo.

O que o activate fez, por baixo, foi pôr a pasta .venv/bin na frente da lista de lugares onde o terminal procura os programas. Por isso python e pip agora são os do ambiente. Ele também criou a variável VIRTUAL_ENV, com o caminho do ambiente ativo (echo $VIRTUAL_ENV mostra).

Ativar vale só para aquele terminal

O ambiente fica ativo na janela (ou aba) de terminal em que você rodou o source, até você desativar ou fechar a janela. Abriu outro terminal? Ele começa com o ambiente desligado, e você ativa de novo. É normal rodar o source .venv/bin/activate toda vez que senta para trabalhar no projeto.

No Windows

A criação é igual (python -m venv .venv), mas a pasta se chama Scripts em vez de bin, e a ativação, no PowerShell, é .venv\Scripts\Activate.ps1. O resto da aula vale igual.


3. O próprio programa sabe se está num ambiente

Um programa Python consegue descobrir qual Python o está rodando. sys.executable é o caminho do Python em uso; sys.base_prefix é a pasta do Python original. Num ambiente virtual, sys.prefix (a pasta do ambiente) é diferente de sys.base_prefix:

import sys

print("Python em uso:", sys.executable)
print("Ambiente virtual?", sys.prefix != sys.base_prefix)
$ python3 onde.py
Python em uso: /usr/bin/python3
Ambiente virtual? False
$ source .venv/bin/activate
(.venv) ana@notebook:~/padaria$ python onde.py
Python em uso: /home/ana/padaria/.venv/bin/python
Ambiente virtual? True

O mesmo arquivo, dois resultados: o que muda é qual Python roda o programa.

Usar o ambiente sem ativar

Ativar é uma comodidade. Dá para chamar o Python do ambiente direto, pelo caminho, sem source nenhum. O resultado é o mesmo:

$ .venv/bin/python onde.py
Python em uso: /home/ana/padaria/.venv/bin/python
Ambiente virtual? True

É assim que se roda um programa de um projeto a partir de outro script ou de um agendador, onde ninguém vai digitar source. O mesmo vale para o pip: .venv/bin/pip install requests instala no ambiente, ativo ou não. E por que o .venv/bin/pip sabe para qual Python instalar? Porque a primeira linha dele diz:

$ cat .venv/bin/pip
#!/home/ana/padaria/.venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal.cli.main import main
if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
    sys.exit(main())

O pip é um programinha Python, e a linha #! do começo (o "shebang") diz qual Python roda ele: o da .venv da padaria, com o caminho completo. Isso vai ser importante no Quando dá errado.

Missão: o pyvenv.cfg tem uma linha chave = valor por configuração. O programa já lê o arquivo; faça ele mostrar Este ambiente usa o Python 3.14.4, pegando o número da linha que começa com version. Dica: linha.split(" = ") separa a chave do valor.

with open("pyvenv.cfg", encoding="utf-8") as arquivo:
    for linha in arquivo:
        linha = linha.strip()
        print(linha)
home = /usr/bin
include-system-site-packages = false
version = 3.14.4
executable = /usr/bin/python3.14
command = /usr/bin/python3 -m venv /home/ana/padaria/.venv
with open("pyvenv.cfg", encoding="utf-8") as arquivo:
    for linha in arquivo:
        linha = linha.strip()
        chave, valor = linha.split(" = ")
        if chave == "version":
            print(f"Este ambiente usa o Python {valor}")

4. Desativando: deactivate

Terminou o trabalho no projeto? deactivate ("desativar") devolve o terminal ao normal. O (.venv) some do prompt, e o python sem 3 volta a não existir:

$ source .venv/bin/activate
(.venv) ana@notebook:~/padaria$ deactivate
$ which python
$ python --version
Comando 'python' não encontrado, você quis dizer:
  comando 'python3' do deb python3
  comando 'python' do deb python-is-python3

O which python não respondeu nada: não há programa com esse nome fora do ambiente. Desativar não apaga nada; o ambiente continua lá, com os pacotes, esperando o próximo source.


5. Cada projeto com o seu

Agora o exemplo da introdução, de verdade. A agenda da Ana precisa do requests 2.32.3. Ela cria o ambiente da agenda com a opção --prompt, que troca o nome que aparece no prompt:

$ mkdir agenda
$ cd agenda
$ python3 -m venv .venv --prompt agenda
$ source .venv/bin/activate
(agenda) ana@notebook:~/agenda$ pip install -q "requests==2.32.3"
(agenda) ana@notebook:~/agenda$ pip list
Package            Version
------------------ ---------
certifi            2026.7.22
charset-normalizer 3.5.2
idna               3.20
pip                25.1.1
requests           2.32.3
urllib3            2.8.0
(agenda) ana@notebook:~/agenda$ deactivate

(O -q, de quiet, "quieto", faz o pip instalar sem imprimir o andamento.) E a lojinha, da aula do pip, continua com a versão dela:

$ cd ../loja
$ source .venv/bin/activate
(.venv) ana@notebook:~/loja$ pip list
Package            Version
------------------ ---------
certifi            2026.7.22
charset-normalizer 3.5.2
idna               3.20
pip                25.1.1
requests           2.34.2
urllib3            2.8.0
(.venv) ana@notebook:~/loja$ deactivate

Duas versões do mesmo pacote no mesmo computador, cada uma na sua caixa, sem uma atrapalhar a outra.

--prompt ou não?

Com várias janelas de terminal abertas, (agenda) diz mais do que (.venv). Mas é só o rótulo: a pasta continua se chamando .venv, e o resto funciona igual.


6. Apagar e recriar: o ambiente é descartável

Um ambiente virtual não guarda nada que você escreveu: o seu código fica fora dele, na pasta do projeto. Por isso ele é descartável. Estragou, ficou com pacotes demais, mudou de versão do Python? Apague e crie de novo. O requirements.txt (aula pip) traz os pacotes de volta:

$ cd loja
$ ls
baixar.py
requirements.txt
$ rm -rf .venv
$ python3 -m venv .venv
$ source .venv/bin/activate
(.venv) ana@notebook:~/loja$ pip install -q -r requirements.txt
(.venv) ana@notebook:~/loja$ pip list
Package            Version
------------------ ---------
certifi            2026.7.22
charset-normalizer 3.5.2
idna               3.20
pip                25.1.1
requests           2.34.2
urllib3            2.8.0
(.venv) ana@notebook:~/loja$ echo $VIRTUAL_ENV
/home/ana/loja/.venv
(.venv) ana@notebook:~/loja$ python baixar.py
Código: 200
Tipo: text/html; charset=utf-8
Tamanho: 577 caracteres

(O ls não mostra a .venv porque o nome começa com ponto.) Os mesmos pacotes, nas mesmas versões, e o programa funcionando. Essa é a rotina de quem recebe um projeto Python de outra pessoa: criar o ambiente, ativar, pip install -r requirements.txt.

rm -rf não tem volta

O rm -rf .venv apaga a pasta e tudo dentro, sem perguntar e sem lixeira. Confira o nome antes de apertar Enter: um espaço a mais (rm -rf . venv) apagaria a pasta atual inteira.


Formas diferentes de usar o ambiente

JeitoExemploQuando usar
Ativar e usar os nomes curtossource .venv/bin/activate e depois python, pipNo dia a dia, trabalhando no projeto pelo terminal
Chamar pelo caminho, sem ativar.venv/bin/python programa.pyEm scripts e agendadores, ou para um comando só
python -m pip no ambiente.venv/bin/python -m pip install requestsQuando você quer ter certeza de qual Python recebe o pacote
Deixar o editor de código cuidarO VS Code (e outros) acha a .venv e ativa sozinho no terminal deleQuando você programa num editor desses

Quando dá errado

Rodar o activate sem o source
$ .venv/bin/activate
bash: .venv/bin/activate: Permissão negada

Parece lógico chamar o script pelo caminho, como um programa. Mas o activate não tem permissão de execução, de propósito (repare no -rw-r--r-- dele no ls -l: nenhum x). Se ele rodasse como programa, mudaria um terminal "filho" que fecha logo em seguida, e o seu terminal continuaria igual. Como consertar: source .venv/bin/activate (ou a forma curta, . .venv/bin/activate, com um ponto e um espaço).

O caminho errado (ou a pasta errada)
$ source venv/bin/activate
bash: venv/bin/activate: Arquivo ou diretório inexistente

A pasta se chama .venv, com ponto, e o comando pediu venv, sem. Muitos tutoriais usam venv ou env; o caminho tem de ser o da pasta que você criou. O mesmo erro aparece se você estiver em outra pasta: o caminho .venv/bin/activate é a partir de onde o terminal está. Como consertar: entre na pasta do projeto (cd ~/padaria) e confira o nome com ls -a.

deactivate sem ambiente ativo
$ deactivate
deactivate: comando não encontrado

O deactivate só existe enquanto um ambiente está ativo: é o próprio activate que o cria. Sem (…) no prompt, não há o que desativar. Não é problema nenhum.

Esqueceu de dar o nome da pasta
$ python3 -m venv
usage: python3 -m venv [-h] [--system-site-packages] [--symlinks | --copies]
                       [--clear] [--upgrade] [--without-pip] [--prompt PROMPT]
                       [--upgrade-deps] [--without-scm-ignore-files]
                       ENV_DIR [ENV_DIR ...]
python3 -m venv: error: the following arguments are required: ENV_DIR

"Os seguintes argumentos são obrigatórios: ENV_DIR" (environment directory, "pasta do ambiente"). A primeira parte é o resumo de uso: entre colchetes ficam as opções que você pode dar; ENV_DIR, sem colchetes, é o que você tem de dar. (Mensagens desse formato vêm do módulo argparse, que você vai usar para fazer os seus próprios programas de terminal na aula argparse.) Como consertar: python3 -m venv .venv.

Copiou o projeto com a .venv junto

A Ana quis fazer uma versão de teste da lojinha e copiou a pasta inteira. Ativou o ambiente da cópia e…

$ cp -r loja loja-copia
$ cd loja-copia
$ source .venv/bin/activate
(.venv) ana@notebook:~/loja-copia$ which python
/home/ana/loja/.venv/bin/python
(.venv) ana@notebook:~/loja-copia$ pip --version
pip 25.1.1 from /home/ana/loja/.venv/lib/python3.14/site-packages/pip (python 3.14)

Sem erro nenhum, mas olhe os caminhos: /home/ana/loja/.venv, e não loja-copia. O ambiente ativado foi o da pasta original. Um pip install agora mudaria a lojinha de verdade, e não a cópia de teste. O motivo: o ambiente guarda o caminho completo de onde foi criado (você viu no pyvenv.cfg e na primeira linha do pip), e o activate também:

$ grep -n "export VIRTUAL_ENV=" .venv/bin/activate
49:        export VIRTUAL_ENV=/home/ana/loja/.venv

Um ambiente virtual não se muda de lugar: nem copiando, nem renomeando a pasta do projeto. Como consertar: na cópia, apague a .venv copiada e crie outra (rm -rf .venv, python3 -m venv .venv, pip install -r requirements.txt). E, para mandar o projeto para alguém, mande o código e o requirements.txt, nunca a .venv.

The virtual environment was not created successfully because ensurepip is not available

Em alguns Ubuntu e Debian, o python3 -m venv falha com essa mensagem (ilustrativa: no computador da Ana o pacote já está instalado). O Ubuntu separa a criação de ambientes num pacote próprio. Como consertar: sudo apt install python3-venv e crie o ambiente de novo (apague antes a pasta que ficou pela metade).

Para fechar, uma comparação que o próprio pip não faz por você: o que muda entre os ambientes de dois projetos.

Missão: os dicionários têm o pip freeze da lojinha e da agenda (pacote → versão). Complete o laço para mostrar, só dos pacotes com versões diferentes, uma linha como requests: loja 2.34.2, agenda 2.32.3.

loja = {"certifi": "2026.7.22", "idna": "3.20", "requests": "2.34.2", "urllib3": "2.8.0"}
agenda = {"certifi": "2026.7.22", "idna": "3.20", "requests": "2.32.3", "urllib3": "2.8.0"}

for pacote in loja:
    print(pacote)
loja = {"certifi": "2026.7.22", "idna": "3.20", "requests": "2.34.2", "urllib3": "2.8.0"}
agenda = {"certifi": "2026.7.22", "idna": "3.20", "requests": "2.32.3", "urllib3": "2.8.0"}

for pacote in loja:
    if loja[pacote] != agenda[pacote]:
        print(f"{pacote}: loja {loja[pacote]}, agenda {agenda[pacote]}")

Referência rápida

ComandoO que faz
python3 -m venv .venvCria o ambiente na pasta .venv
python3 -m venv .venv --prompt nomeCria com outro rótulo no prompt: (nome)
source .venv/bin/activateAtiva o ambiente neste terminal (no Windows: .venv\Scripts\Activate.ps1)
deactivateDesativa
which pythonMostra qual Python roda com esse nome
echo $VIRTUAL_ENVMostra o caminho do ambiente ativo
.venv/bin/python programa.pyRoda com o Python do ambiente, sem ativar
rm -rf .venvApaga o ambiente (o código do projeto fica)
pip install -r requirements.txtRecoloca os pacotes num ambiente novo
Em PythonO que é
sys.executableO caminho do Python que está rodando o programa
sys.prefixA pasta do ambiente em uso (ou do Python do sistema)
sys.base_prefixA pasta do Python original
sys.prefix != sys.base_prefixTrue dentro de um ambiente virtual
SintomaCausa provável
bash: .venv/bin/activate: Permissão negadaFaltou o source na frente
bash: venv/bin/activate: Arquivo ou diretório inexistenteNome da pasta errado ou terminal em outra pasta
deactivate: comando não encontradoNenhum ambiente ativo
error: the following arguments are required: ENV_DIRFaltou o nome da pasta no python3 -m venv
which python aponta para outra pastaA .venv foi copiada ou movida: recrie
ModuleNotFoundError de um pacote que você instalouO ambiente não está ativo (sem (.venv) no prompt)

Exercícios

1. Criar

Complete o comando que cria um ambiente virtual na pasta .venv:

python3 -m .venv

2. Ativar

Complete o comando que ativa o ambiente no terminal:

.venv/bin/activate

3. Desativar

Qual comando desliga o ambiente ativo?

4. Como você sabe, olhando o terminal, que um ambiente virtual está ativo?

5. Por que cada projeto deve ter o seu ambiente virtual?

6. A Ana vai mandar a lojinha para a Bia. O que ela deve mandar?

Missão final: o ambiente está ativo?

Missão: o activate põe o nome do ambiente na frente do prompt. Complete a função prompt para devolver (.venv) ana@notebook:~/loja$ quando ambiente tiver um nome e só ana@notebook:~/agenda$ quando ambiente for None (aula O Valor None).

def prompt(pasta, ambiente):
    base = f"ana@notebook:{pasta}$"
    return base


print("Com ambiente:", prompt("~/loja", ".venv"))
print("Sem ambiente:", prompt("~/agenda", None))
def prompt(pasta, ambiente):
    base = f"ana@notebook:{pasta}$"
    if ambiente is None:
        return base
    return f"({ambiente}) {base}"


print("Com ambiente:", prompt("~/loja", ".venv"))
print("Sem ambiente:", prompt("~/agenda", None))

Resumo

  • Um ambiente virtual é uma pasta (o costume é .venv) com um Python particular e os pacotes de um projeto.
  • Crie com python3 -m venv .venv, ative com source .venv/bin/activate, desative com deactivate.
  • Ativo, o prompt começa com (.venv), e python e pip são os do ambiente (which python confirma). Vale só para aquele terminal.
  • Sem ativar, chame pelo caminho: .venv/bin/python programa.py.
  • Cada projeto com o seu: dois projetos podem usar versões diferentes do mesmo pacote no mesmo computador.
  • O ambiente é descartável e preso ao lugar onde foi criado: não copie nem mova; apague e recrie com pip install -r requirements.txt.