Como obter o código de saída ao usar o método de comunicação por subprocesso do Python?

186

Como recupero o código de saída ao usar o subprocessmódulo e o communicate()método do Python ?

Código relevante:

import subprocess as sp
data = sp.Popen(openRTSP + opts.split(), stdout=sp.PIPE).communicate()[0]

Eu deveria estar fazendo isso de outra maneira?

Aproveite a noite
fonte

Respostas:

266

Popen.communicateirá definir o returncodeatributo quando terminar (*). Aqui está a seção de documentação relevante:

Popen.returncode 
  The child return code, set by poll() and wait() (and indirectly by communicate()). 
  A None value indicates that the process hasnt terminated yet.

  A negative value -N indicates that the child was terminated by signal N (Unix only).

Então você pode fazer (eu não testei, mas deve funcionar):

import subprocess as sp
child = sp.Popen(openRTSP + opts.split(), stdout=sp.PIPE)
streamdata = child.communicate()[0]
rc = child.returncode

(*) Isso acontece devido à maneira como é implementado: depois de configurar os threads para ler os fluxos da criança, basta chamar wait.

Eli Bendersky
fonte
34
Este exemplo me ajudou, mas seria bom se os exemplos não fizessem o padrão "import subprocess as sp" de importar algo padrão como uma abreviação obscura. Embora isso elimine 8 caracteres do código a seguir, também dificulta a compreensão e a reutilização.
Ublycoyote # 19/16
16
@uglycoyote Não existe uma regra que diga que você deve copiar e colar. Basta redigitá-lo como quiser, são 4 linhas iguais.
Jason C #
5
@uglycoyote você também pode editar-lo para ser algo como from subprocess import Popene, em seguida, é só usar Popenem vez de subprocess(or sp).Popenque eu diria que provavelmente aumenta a legibilidade e encurta linhas
Mitch
2
Sim ... deve ligar process.communicate()e depois atribuir returncodea alguma variável. Se a atribuição for feita antes da chamada communicate, é None.
WesternGun
1
É possível mostrar o código de retorno sem redirecionar o canal? Eu estou chamando um código bash e eu gostaria de ver a saída em tempo real no terminal
Nisba
10

Você deve primeiro verificar se o processo concluiu a execução e se o código de retorno foi lido usando o .waitmétodo Isso retornará o código. Se você quiser acessar mais tarde, ele será armazenado como .returncodeno Popenobjeto.

Noufal Ibrahim
fonte
24
.communicate()já aguarda a finalização do subprocesso.
Caracol mecânico
8

.poll() atualizará o código de retorno.

Experimentar

child = sp.Popen(openRTSP + opts.split(), stdout=sp.PIPE)
returnCode = child.poll()

Além disso, depois de .poll()chamado, o código de retorno está disponível no objeto como child.returncode.

Matthew Vernon
fonte
quando eu fiz isso .poll () estava vazio. Eu tive que executar child.communicate () na linha acima child.poll () para que isso funcionasse.
NateW
1
Eu acho que você pretendia usar .wait () em vez de .poll (), conforme a documentação: docs.python.org/3/library/subprocess.html . Observe que .wait () usa um parâmetro de tempo limite opcional que pode ser conveniente.
gg99 12/03/19
7

exitcode = data.wait(). O processo filho será bloqueado Se gravar na saída / erro padrão e / ou ler a partir da entrada padrão, e não houver pares.

khachik
fonte
1

Isso funcionou para mim. Também imprime a saída retornada pelo processo filho

child = subprocess.Popen(serial_script_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    retValRunJobsSerialScript = 0
    for line in child.stdout.readlines():
        child.wait()
        print line           
    retValRunJobsSerialScript= child.returncode
Chinni Mahesh
fonte