Eu tenho um script parecido com este:
export foo=/tmp/foo
export bar=/tmp/bar
Toda vez que eu construo, eu executo 'source init_env' (onde init_env é o script acima) para configurar algumas variáveis.
Para fazer o mesmo em Python, coloquei este código em execução,
reg = re.compile('export (?P<name>\w+)(\=(?P<value>.+))*')
for line in open(file):
m = reg.match(line)
if m:
name = m.group('name')
value = ''
if m.group('value'):
value = m.group('value')
os.putenv(name, value)
Mas então alguém decidiu que seria bom adicionar uma linha como a seguinte ao init_env
arquivo:
export PATH="/foo/bar:/bar/foo:$PATH"
Obviamente, meu script Python se desfez. Eu poderia modificar o script Python para lidar com essa linha, mas ele apenas será interrompido mais tarde, quando alguém surgir com um novo recurso para usar no init_env
arquivo.
A questão é se existe uma maneira fácil de executar um comando Bash e deixá-lo modificar o meu os.environ
?
Respostas:
O problema com sua abordagem é que você está tentando interpretar scripts bash. Primeiro, você apenas tenta interpretar a instrução de exportação. Então você percebe que as pessoas estão usando expansão variável. Posteriormente, as pessoas colocarão condicionais em seus arquivos ou substituições de processos. No final, você terá um interpretador de script bash completo com zilhões de bugs. Não faça isso.
Deixe o Bash interpretar o arquivo para você e coletar os resultados.
Você pode fazer assim:
Certifique-se de lidar com os erros caso o bash falhe
source init_env
, ou o próprio bash falhe ao executar, ou o subprocesso falhe ao executar o bash, ou quaisquer outros erros.o
env -i
no início da linha de comando cria um ambiente limpo. isso significa que você só obterá as variáveis de ambiente deinit_env
. se desejar o ambiente de sistema herdado, omitaenv -i
.Leia a documentação sobre o subprocesso para mais detalhes.
Nota: isso irá capturar apenas variáveis definidas com a
export
instrução, poisenv
imprime apenas variáveis exportadas.Aproveitar.
Observe que a documentação do Python diz que se você deseja manipular o ambiente, deve manipular
os.environ
diretamente em vez de usaros.putenv()
. Eu considero isso um bug, mas estou divagando.fonte
proc.stdout()
bytes de rendimento, portanto, eu estava ficandoTypeError
ligadoline.partition()
. A conversão para string comline.decode().partition("=")
resolveu o problema.['env', '-i', 'bash', '-c', 'source .bashrc && env']
para me dar apenas as variáveis de ambiente definidas pelo arquivo rcUsando picles:
Atualizada:
Isso usa json, subprocess, e usa explicitamente / bin / bash (para suporte ubuntu):
fonte
/bin/dash
, que não conhece osource
comando. Para usá-lo no Ubuntu, você deve executar/bin/bash
explicitamente, por exemplo, usandopenv = subprocess.Popen(['/bin/bash', '-c', '%s && %s' %(source,dump)], stdout=subprocess.PIPE).stdout
(usa osubprocess
módulo mais recente que deve ser importado).Em vez de ter sua fonte de script Python como o script bash, seria mais simples e mais elegante ter uma fonte de script wrapper
init_env
e então executar seu script Python com o ambiente modificado.fonte
bash --rcfile init_env -c ./script.py
Atualizado a resposta de @lesmana para Python 3. Observe o uso de
env -i
que evita que variáveis de ambiente estranhas sejam definidas / redefinidas (potencialmente incorretamente devido à falta de manipulação de variáveis env multilinha).fonte
Exemplo de envolvimento da excelente resposta de Brian em uma função:
Estou usando esta função de utilitário para ler credenciais aws e arquivos .env do docker com
include_unexported_variables=True
.fonte