Como chegar ambiente a partir de um subprocesso?
-
06-07-2019 - |
Pergunta
Eu quero chamar um processo por meio de um programa de python, no entanto, este processo precisa de algumas variáveis ??de ambiente específicas que são definidas por outro processo. Como posso obter as primeiras variáveis ??de ambiente processo para passá-las para o segundo?
Isto é o que o olhar programa como:
import subprocess
subprocess.call(['proc1']) # this set env. variables for proc2
subprocess.call(['proc2']) # this must have env. variables set by proc1 to work
mas o que processo não compartilham o mesmo ambiente. Note-se que estes programas não são minhas (o primeiro é grande e feio arquivo .bat eo segundo um soft proprietário) por isso não pode modificá-los (ok, eu posso extrair tudo o que eu preciso do .bat, mas é muito combersome ).
NB .: Estou usando o Windows, mas eu prefiro uma solução multi-plataforma (mas o meu problema não aconteceria em um Unix-like ...)
Solução
Uma vez que você está aparentemente no Windows, você precisa de uma resposta do Windows.
Criar um arquivo de lote invólucro, por exemplo. "Run_program.bat", e executar os dois programas:
@echo off
call proc1.bat
proc2
O script será executado e definir suas variáveis ??de ambiente. Ambos os scripts são executados no mesmo intérprete (exemplo cmd.exe), então as variáveis ??prog1.bat conjuntos irá ser definido quando PROG2 é executado.
Não terrivelmente bonito, mas ele vai trabalhar.
(pessoas Unix, você pode fazer a mesma coisa em um script:. "File.sh source")
Outras dicas
Aqui está um exemplo de como você pode extrair as variáveis ??de ambiente de um lote ou arquivo cmd sem criar um script. Desfrute.
from __future__ import print_function
import sys
import subprocess
import itertools
def validate_pair(ob):
try:
if not (len(ob) == 2):
print("Unexpected result:", ob, file=sys.stderr)
raise ValueError
except:
return False
return True
def consume(iter):
try:
while True: next(iter)
except StopIteration:
pass
def get_environment_from_batch_command(env_cmd, initial=None):
"""
Take a command (either a single command or list of arguments)
and return the environment created after running that command.
Note that if the command must be a batch file or .cmd file, or the
changes to the environment will not be captured.
If initial is supplied, it is used as the initial environment passed
to the child process.
"""
if not isinstance(env_cmd, (list, tuple)):
env_cmd = [env_cmd]
# construct the command that will alter the environment
env_cmd = subprocess.list2cmdline(env_cmd)
# create a tag so we can tell in the output when the proc is done
tag = 'Done running command'
# construct a cmd.exe command to do accomplish this
cmd = 'cmd.exe /s /c "{env_cmd} && echo "{tag}" && set"'.format(**vars())
# launch the process
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=initial)
# parse the output sent to stdout
lines = proc.stdout
# consume whatever output occurs until the tag is reached
consume(itertools.takewhile(lambda l: tag not in l, lines))
# define a way to handle each KEY=VALUE line
handle_line = lambda l: l.rstrip().split('=',1)
# parse key/values into pairs
pairs = map(handle_line, lines)
# make sure the pairs are valid
valid_pairs = filter(validate_pair, pairs)
# construct a dictionary of the pairs
result = dict(valid_pairs)
# let the process finish
proc.communicate()
return result
Assim, para responder sua pergunta, você poderia criar um arquivo .py que faz o seguinte:
env = get_environment_from_batch_command('proc1')
subprocess.Popen('proc2', env=env)
Como você disse, os processos não compartilham o meio ambiente -. Então, o que você literalmente perguntar não é possível, não só em Python, mas com qualquer linguagem de programação
O que você pode fazer é colocar as variáveis ??de ambiente em um arquivo ou em uma tubulação, e quer
- tem o processo pai lê-los e passá-los para proc2 antes proc2 é criado, ou
- Have proc2 lê-los e configurá-los localmente
O último exigiria a cooperação de proc2; o primeiro requer que as variáveis ??se tornar conhecido antes proc2 é iniciado.
Duas coisas saltam à mente: (1) fazer os processos compartilham o mesmo ambiente, combinando-as de alguma forma para o mesmo processo, ou (2) ter a saída produzir o primeiro processo que contém as variáveis ??de ambiente relevantes, dessa forma Python pode lê-lo e construir o ambiente para o segundo processo. Eu acho que (embora eu não estou 100% de certeza) de que não há nenhuma maneira de obter o ambiente de um subprocesso como você está esperando para fazer.
O módulo padrão do Python multiprocessamento ter um sistema de filas que lhe permitem passar pickle objeto -able para ser passado através de processos. Também processos podem trocar mensagens (um objeto em conserva) usando os.pipe. Lembre-se que os recursos (por exemplo: conexão com o banco) e pega (por exemplo: identificadores de arquivo). Não pode ser em conserva
Você pode encontrar este link interessante: comunicação entre processos com multiprocessamento
Além disso, o PyMOTw sobre multiprocessamento vale a pena mencionar: multiprocessamento Basics
sorry for my ortografia
Ambiente é herdada do processo pai. Defina o ambiente que você precisa no script principal, não um subprocesso (criança).