Qual é a diferença entre o subprocesso Popen e a chamada (como posso usá-los)?

178

Eu quero chamar um programa externo do Python. Eu usei os dois Popen()e call()para fazer isso.

Qual a diferença entre os dois?

Meu objetivo específico é executar o seguinte comando do Python. Não tenho certeza de como os redirecionamentos funcionam.

./my_script.sh > output

Eu li a documentação e diz que call()é uma função de conveniência ou uma função de atalho. Perdemos algum poder usando em call()vez de Popen()?

varunl
fonte
Que parte da documentação o confundiu? A definição de call()parece ser muito clara. Você pode fornecer uma cotação ou um link para saber o que focar em uma resposta?
S.Lott

Respostas:

265

Existem duas maneiras de fazer o redirecionamento. Ambos se aplicam a subprocess.Popenou subprocess.call.

  1. Defina o argumento da palavra-chave shell = Trueou executable = /path/to/the/shelle especifique o comando exatamente como você o possui.

  2. Como você está apenas redirecionando a saída para um arquivo, defina o argumento de palavra-chave

    stdout = an_open_writeable_file_object

    onde o objeto aponta para o outputarquivo.

subprocess.Popené mais geral que subprocess.call.

Popennão bloqueia, permitindo que você interaja com o processo enquanto estiver em execução ou continue com outras coisas no seu programa Python. A chamada para Popenretorna um Popenobjeto.

call faz bloco. Embora ele suporte todos os mesmos argumentos do Popenconstrutor, para que você ainda possa definir a saída do processo, variáveis ​​ambientais, etc., seu script aguarda a conclusão do programa e callretorna um código que representa o status de saída do processo.

returncode = call(*args, **kwargs) 

é basicamente o mesmo que chamar

returncode = Popen(*args, **kwargs).wait()

callé apenas uma função de conveniência. Sua implementação no CPython está em subprocess.py :

def call(*popenargs, timeout=None, **kwargs):
    """Run command with arguments.  Wait for command to complete or
    timeout, then return the returncode attribute.

    The arguments are the same as for the Popen constructor.  Example:

    retcode = call(["ls", "-l"])
    """
    with Popen(*popenargs, **kwargs) as p:
        try:
            return p.wait(timeout=timeout)
        except:
            p.kill()
            p.wait()
            raise

Como você pode ver, é um invólucro fino ao redor Popen.

agf
fonte
17
Basicamente Popen e call são funções assíncronas e síncronas, respectivamente usadas para executar comandos do Linux.
user3016020
1
Qual é a vantagem de usar o popen? Não seria seguro esperar até que o programa chamado termine primeiro?
Tom
4
@ Tom Muitas vezes não. E se você quiser ler alguma saída, enviar mais entradas para o programa, ler mais saídas resultantes dessa entrada, repita?
agf
@ user3016020 Presumo que isso também se aplique aos comandos do Windows? Certo?
domih
7

A outra resposta é muito completa, mas aqui está uma regra prática:

  • call está bloqueando:

    call('notepad.exe')
    print('hello')  # only executed when notepad is closed
  • Popen é sem bloqueio:

    Popen('notepad.exe')
    print('hello')  # immediately executed
Basj
fonte