Ative um virtualenv com um script Python

91

Quero ativar uma instância virtualenv de um script Python.

Eu sei que é muito fácil de fazer, mas todos os exemplos que vi usam para executar comandos dentro do env e, em seguida, fecham o subprocesso.

Eu simplesmente quero ativar o virtualenv e retornar ao shell, da mesma forma que bin / activate faz.

Algo assim:

$me: my-script.py -d env-name
$(env-name)me:

Isso é possível?

Relevante:

virtualenv ›Invocar um env a partir de um script

h3.
fonte

Respostas:

88

Se você deseja executar um subprocesso Python no virtualenv, pode fazer isso executando o script usando o interpretador Python que reside dentro do diretório / bin / do virtualenv:

import subprocess

# Path to a Python interpreter that runs any Python script
# under the virtualenv /path/to/virtualenv/
python_bin = "/path/to/virtualenv/bin/python"

# Path to the script that must run under the virtualenv
script_file = "must/run/under/virtualenv/script.py"

subprocess.Popen([python_bin, script_file])

No entanto, se você deseja ativar o virtualenv no interpretador Python atual em vez de um subprocesso, pode usar o activate_this.pyscript:

# Doing execfile() on this file will alter the current interpreter's
# environment so you can import libraries in the virtualenv
activate_this_file = "/path/to/virtualenv/bin/activate_this.py"

execfile(activate_this_file, dict(__file__=activate_this_file))
Mentira ryan
fonte
1
//, Essa última linha no primeiro bloco de código nesta resposta não deveria ser lida como segue subprocess.Popen([venv_python_file, script_file]):?
Nathan Basanese
// Além disso, existe uma maneira de executar o script_filede um local arbitrário ou ele precisa estar no virtualenvdiretório?
Nathan Basanese
Corrigido, obrigado por perceber o erro. Quanto à sua segunda pergunta, script_filenão precisa estar no diretório virtualenv, pode estar em qualquer lugar.
Lie Ryan
Como posso desativar o ambiente virtual, se estou usando a segunda opção?
falsePockets de
@falsePockets: Problema XY , por que você sempre quer fazer isso?
Lie Ryan,
42

A solução mais simples para executar seu script sob o intérprete do virtualenv é substituir a linha shebang padrão pelo caminho para o intérprete do virtualenv, como no início do script:

#!/path/to/project/venv/bin/python

Torne o script executável:

chmod u+x script.py

Execute o script:

./script.py

Voila!

nafooesi
fonte
2
1 para elegância. Observe que no Windows isso requer um ambiente compatível com POSIX que entenda linhas shebang como cygwin ou msys
qneill
1
Funciona para python 3.6.3 e windows 10!
toonarmycaptain
Acho que posso ter entendido mal a pergunta original. Ele deseja ativar o ambiente virtual com um script e retornar ao shell com o ambiente ativado. Minha resposta executa o script no ambiente virtual, mas o shell retornado não retém o ambiente. A solução moderna é virtualenvwrapper: virtualenvwrapper.readthedocs.io/en/latest/# . Permite ativar e alternar entre diferentes virtuaisenvs.
nafooesi
20

Acontece que, sim, o problema não é simples, mas a solução é.

Primeiro, tive que criar um script de shell para envolver o comando "source". Dito isto, usei o "." em vez disso, porque li que é melhor usá-lo do que a fonte para scripts Bash.

#!/bin/bash
. /path/to/env/bin/activate

Então, a partir do meu script Python, posso simplesmente fazer isso:

import os
os.system('/bin/bash --rcfile /path/to/myscript.sh')

Todo o truque está dentro do --rcfileargumento.

Quando o interpretador Python sai, ele deixa o shell atual no ambiente ativado.

Ganhar!

h3.
fonte
3
Eu realmente não entendo. Por que você simplesmente não faz isso: os.system('/bin/bash --rcfile path/to/env/activate') você sabe, quando uma instância do bash é iniciada, ele recebe .bashrc como um argumento para o --rcfile. Portanto, apenas especifique que o rcfile é o seu arquivo de ativação ... Não?
Depado
@Depado Acabei de tentar sua solução e isso irá ativar o shell dentro do python. pelo menos quando tento na casca. >>> os.system ('/ bin / bash --rcfile / var / envs / test / bin / activate') (test) tcraig @ tallis-desktop: ~ $ (test) tcraig @ tallis-desktop: ~ $ ls -l total 706288
Trenton
Talvez, mas isso funciona em um script. O único inconveniente com essa técnica é que você não obtém todos os seus aliases e tudo o que tinha em ~ / .bashrc. Mas estou bem com isso. Por exemplo, o comando "ls" não tem cor. Mas tudo funciona para mim. Quando eu quero sair, eu apenas Ctrl + D
Depado
7
"Quando o interpretador python sai, ele deixa o shell atual no ambiente ativado" O quê? Ele gera um shell totalmente novo como um subprocesso e espera até que seja concluído.
Kos
Para evitar a criação de mais arquivos novos em meu repositório e também replicar a configuração atual do bash, fiz o seguinte:cat ~/.bashrc env/bin/activate > env/bin/activate2 && /bin/bash --rcfile env/bin/activate2
WhyWhat
17

Para executar outro ambiente Python de acordo com a documentação oficial da Virtualenv , na linha de comando você pode especificar o caminho completo para o binário executável do Python, apenas isso (não há necessidade de ativar o virtualenv antes):

/path/to/virtualenv/bin/python

O mesmo se aplica se você deseja invocar um script da linha de comando com seu virtualenv. Você não precisa ativá-lo antes:

me$ /path/to/virtualenv/bin/python myscript.py

O mesmo para um ambiente Windows (seja da linha de comando ou de um script):

> \path\to\env\Scripts\python.exe myscript.py
Mariano ruiz
fonte
2
A pergunta é: Ativar um virtualenv com um script python (NÃO do Shell)
Zaheer
3
Sim, meu ponto é que você pode simplesmente chamar o tempo de execução do python de um ambiente virtual sem a necessidade de ativá-lo antes, do console ou de um script. Vou esclarecer a resposta, obrigado!
Mariano Ruiz de
Ó meu Deus! Eu não pensei sobre isso. esta é a única solução que funcionou para mim :). Agora, quando estou executando o script python do php, estou usando: "path / to / virtualenv / bin / python mypythonscript.py"
Zaheer
6

Apenas uma solução simples que funciona para mim. Não sei por que você precisa do script Bash, que basicamente executa uma etapa inútil (estou errado?)

import os
os.system('/bin/bash  --rcfile flask/bin/activate')

O que basicamente faz o que você precisa:

[hellsing@silence Foundation]$ python2.7 pythonvenv.py
(flask)[hellsing@silence Foundation]$

Então, em vez de desativar o ambiente virtual, basta Ctrl+ Dou sair. Essa é uma solução possível ou não é o que você queria?

Depado
fonte
2

O ambiente do processo filho é perdido no momento em que deixa de existir, e mover o conteúdo do ambiente de lá para o pai é um tanto complicado.

Você provavelmente precisa gerar um script de shell (você pode gerar um dinamicamente em / tmp) que produzirá as variáveis ​​de ambiente virtualenv em um arquivo, que você então lê no processo Python pai e coloca em os.environ.

Ou você simplesmente analisa o script de ativação usando para a linha em aberto ("bin / activate"), extrai manualmente as coisas e coloca em os.environ. É complicado, mas não impossível.

Mikko Ohtamaa
fonte
2
Você quer dizer algo assim? bitbucket.org/ianb/virtualenv/src/1f9dfb2437f1/…
h3.
2

A melhor resposta só funciona para Python 2.x

Para Python 3.x, use este:

activate_this_file = "/path/to/virtualenv/bin/activate_this.py"

exec(compile(open(activate_this_file, "rb").read(), activate_this_file, 'exec'), dict(__file__=activate_this_file))

Referência: o que é uma alternativa para execfile no Python 3?

Asaad
fonte
1
o que é activate_this.py
Randy Pen
1
@randyPen, o arquivo activate_this.py é adicionado automaticamente quando você constrói o virtualenv em seu diretório de projeto. (ou seja, /project/directory/venv/bin/activate_this.py)
Teoricamente
-2

Você deve criar todos os seus virtualenvs em uma pasta, como virt.

Supondo que o nome da pasta virtualenv seja virt, se não, altere-o

cd
mkdir custom

Copie as linhas abaixo ...

#!/usr/bin/env bash
ENV_PATH="$HOME/virt/$1/bin/activate"
bash --rcfile $ENV_PATH -i

Crie um arquivo de script de shell e cole as linhas acima ...

touch custom/vhelper
nano custom/vhelper

Conceda permissão executável para seu arquivo:

sudo chmod +x custom/vhelper

Agora exporte o caminho da pasta personalizada para que você possa encontrá-lo na linha de comando clicando na guia ...

exportar PATH = $ PATH: "$ HOME / custom"

Agora você pode usá-lo de qualquer lugar, basta digitar o comando abaixo ...

vhelper YOUR_VIRTUAL_ENV_FOLDER_NAME

Suponha que seja abc então ...

vhelper abc
SR_Mehta
fonte