Iniciando e controlando um processo externo via stdin/stdout com python
-
23-08-2019 - |
Pergunta
Preciso iniciar um processo externo que seja controlado por meio de mensagens enviadas via STDIN e STDOUT. Usando o subprocess.popen, sou capaz de iniciar o processo, mas não consigo controlar a execução via stdin, conforme necessário.
O fluxo do que estou tentando concluir é:
- Inicie o processo externo
- Itera para um número de etapas
- Diga ao processo externo para concluir a próxima etapa de processamento, escrevendo um personagem de nova linha para o seu stdin
- Aguarde o processo externo sinalizar, ele concluiu a etapa escrevendo um personagem de nova linha para o seu stdout
- Feche o STDIN do processo externo para indicar com o processo externo que a execução foi concluída.
Eu criei o seguinte até agora:
process=subprocess.Popen([PathToProcess],stdin=subprocess.PIPE,stdout=subprocess.PIPE);
for i in xrange(StepsToComplete):
print "Forcing step # %s"%i
process.communicate(input='\n')
Quando executo o código acima, o ' n' não é comunicado ao processo externo e nunca vou além da etapa nº 0. O código bloqueia em Process.Communicate () e não prossegue mais. Estou usando o método Communicate () incorretamente?
Além disso, como eu implementaria a funcionalidade "Aguarde até que o processo externo escreva uma nova linha"?
Solução
Process.Communicate (input = ' n') está errado. Se você perceber nos documentos do Python, ele grava sua corda no stdin da criança, lê toda a saída da criança até que a criança saia. De doc.python.org:
Popen.Communicate (input = Nenhum) Interaja com o processo: Envie dados para Stdin. Leia os dados do stdout e Stderr, até o final do arquivo ser atingido. Aguarde o processo de rescisão do processo. O argumento de entrada opcional deve ser uma string a ser enviada ao processo filho, ou nenhum, se nenhum dado deve ser enviado para a criança.
Em vez disso, você quer apenas escrever para o stdin da criança. Em seguida, leia o seu loop.
Algo mais como:
process=subprocess.Popen([PathToProcess],stdin=subprocess.PIPE,stdout=subprocess.PIPE);
for i in xrange(StepsToComplete):
print "Forcing step # %s"%i
process.stdin.write("\n")
result=process.stdout.readline()
Isso fará algo mais parecido com o que você deseja.
Outras dicas
Você poderia usar Twisted, usando Reactor.spawnProcess e LineReCeiver.