Você já pensou em como as bibliotecas de ambiente virtual funcionam no Python? Neste artigo, proponho me familiarizar com o conceito principal usado por todas as bibliotecas de ambientes, como virtualenv, virtualenvwrapper, conda, pipenv.
Inicialmente, no Python não havia capacidade interna de criar ambientes, e esse recurso foi implementado como um hack. Como se viu, todas as bibliotecas são baseadas em um recurso muito simples do interpretador python.
Quando o Python inicia o intérprete, ele começa a procurar o diretório com os módulos (site-packages). A pesquisa começa com o diretório pai em relação à localização física do executável do intérprete (python.exe). Se a pasta do módulo não for encontrada, o Python aumentará um nível e o fará até o diretório raiz ser atingido. Para entender que esse é um diretório com módulos, o Python procura o módulo os, que deve estar no arquivo os.py e é necessário para o python funcionar.
Vamos imaginar que nosso intérprete esteja localizado em 
/usr/dev/lang/bin/python . Em seguida, os caminhos de pesquisa terão a seguinte aparência:
 /usr/dev/lang/lib/python3.7/os.py /usr/dev/lib/python3.7/os.py /usr/lib/python3.7/os.py /lib/python3.7/os.py 
Como você pode ver, o Python adiciona um prefixo especial ( 
lib/python$VERSION/os.py ) ao nosso caminho. Assim que o intérprete encontra a primeira correspondência (a presença do arquivo os.py), ele altera 
sys.prefix e 
sys.exec_prefix para esse caminho (com o prefixo removido). Se, por algum motivo, nenhuma correspondência for encontrada, o caminho padrão será usado, compilado no intérprete.
Agora vamos ver como uma das bibliotecas mais antigas e famosas, virtualenv, faz isso.
 user@arb:/usr/home/test 
Após a execução, ele cria diretórios adicionais:
 user@arb:/usr/home/test/ENV 
Como você pode ver, o ambiente virtual foi criado copiando o binário Python para uma pasta local (ENV / bin / python). Também podemos notar que a pasta pai contém 
links simbólicos para os arquivos da biblioteca padrão do python. Não podemos criar um link simbólico para o arquivo executável, pois o intérprete ainda o renomeará para o caminho real.
Agora vamos ativar nosso ambiente:
 user@arb:/usr/home/test 
Este comando altera a variável de ambiente $ PATH para que o comando 
python aponte para nossa versão local do python. Isso é conseguido substituindo o caminho local da pasta bin no início da linha $ PATH, para que o caminho local tenha precedência sobre todos os caminhos à direita.
 export "/usr/home/test/ENV/bin:$PATH" echo $PATH 
Se você executar o script nesse ambiente, ele será executado usando o binário em 
/usr/home/test/ENV/bin/python . O intérprete usará esse caminho como ponto de partida para encontrar módulos. No nosso caso, os módulos da biblioteca padrão serão encontrados no caminho 
/usr/home/test/ENV/lib/python3.7/ .
Este é o principal truque, graças ao qual todas as bibliotecas para trabalhar com ambientes virtuais funcionam.
Melhorias no Python 3
A partir da versão Python 3.3, um novo padrão apareceu, chamado 
PEP 405 , que introduz um novo mecanismo para ambientes leves.
Este PEP adiciona uma etapa extra ao processo de busca. Se você criar o 
pyenv.cfg configuração 
pyenv.cfg , em vez de copiar o binário Python e todos os seus módulos, poderá simplesmente indicar sua localização nesta configuração.
Esse recurso é usado ativamente pelo módulo 
venv padrão, que apareceu no Python 3.
 user@arb:/usr/home/test2 
 user@arb:/usr/home/test2 
Graças a esta configuração, em vez de copiar o binário, o venv simplesmente cria um link para ele. Se o parâmetro 
include-system-site-packages alterado para 
true , todos os módulos da biblioteca padrão serão automaticamente acessíveis no ambiente virtual.
Apesar dessas mudanças, a maioria das bibliotecas de terceiros para trabalhar com ambientes virtuais usa a abordagem antiga.
PS: Eu sou o autor deste artigo, você pode fazer qualquer pergunta.