Esta documentação é de uma versão antiga do Python que não é mais atualizada. Você deveria atualizar e ler a documentação do Python para versão estável atual.

# Subprocesso

Esta seção descreve APIs async/await asyncio de alto nível para criar e gerenciar subprocessos.

Aqui está um exemplo de como asyncio pode executar um comando shell e obter o seu resultado:

    import asyncio

    async def run(cmd):
        proc = await asyncio.create_subprocess_shell(
            cmd,
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE)

        stdout, stderr = await proc.communicate()

        print(f'[{cmd!r} exited with {proc.returncode}]')
        if stdout:
            print(f'[stdout]\n{stdout.decode()}')
        if stderr:
            print(f'[stderr]\n{stderr.decode()}')

    asyncio.run(run('ls /zzz'))

irá exibir:

    ['ls /zzz' exited with 1]
    [stderr]
    ls: /zzz: No such file or directory

Devido ao fato que todas as funções de subprocessos asyncio são assíncronas e asyncio fornece muitas ferramentas para trabalhar com tais funções, é fácil executar e monitorar múltiplos subprocessos em paralelo. É na verdade trivial modificar o exemplo acima para executar diversos comandos simultaneamente:

    async def main():
        await asyncio.gather(
            run('ls /zzz'),
            run('sleep 1; echo "hello"'))

    asyncio.run(main())

Veja também a subseção Exemplos.

## Criando Subprocessos

coroutine `asyncio.``create_subprocess_exec`(program, *args, stdin=None, stdout=None, stderr=None, loop=None, limit=None, **kwds)

  Cria um subprocesso.

  O argumento limit define o buffer limite para os wrappers `StreamReader` para `Process.stdout` e `Process.stderr` (se `subprocess.PIPE` for passado para os argumentos stdout e stderr).

  Retorna uma instância de `Process`.

  Veja a documentação de `loop.subprocess_exec()` para outros parâmetros.

coroutine `asyncio.``create_subprocess_shell`(cmd, stdin=None, stdout=None, stderr=None, loop=None, limit=None, **kwds)

  Executa o comando cmd no shell.

  O argumento limit define o buffer limite para os wrappers `StreamReader` para `Process.stdout` e `Process.stderr` (se `subprocess.PIPE` for passado para os argumentos stdout e stderr).

  Retorna uma instância de `Process`.

  Veja a documentação de `loop.subprocess_shell()` para outros parâmetros.

Importante

É responsabilidade da aplicação garantir que todos os espaços em branco e caracteres especiais tenham aspas apropriadamente para evitar vulnerabilidades de injeção de shell. A função `shlex.quote()` pode ser usada para escapar espaços em branco e caracteres especiais de shell apropriadamente em strings que serão usadas para construir comandos shell.

Nota

The default asyncio event loop implementation on Windows does not support subprocesses. Subprocesses are available for Windows if a `ProactorEventLoop` is used. See Subprocess Support on Windows for details.

Ver também

asyncio também tem as seguintes APIs de baixo nível para trabalhar com subprocessos: `loop.subprocess_exec()`, `loop.subprocess_shell()`, `loop.connect_read_pipe()`, `loop.connect_write_pipe()`, assim como os Transportes de Subprocesso e Protocolos de Subprocesso.

## Constantes

`asyncio.subprocess.``PIPE`

  Pode ser passado para os parâmetros stdin, stdout ou stderr.

  Se PIPE for passado para o argumento stdin, o atributo `Process.stdin` irá apontar para uma instância `StreamWriter`.

  Se PIPE for passado para os argumentos stdout ou stderr, os atributos `Process.stdout` e `Process.stderr` irão apontar para instâncias `StreamReader`.

`asyncio.subprocess.``STDOUT`

  Valor especial que pode ser usado como o argumento stderr e indica que a saída de erro padrão deve ser redirecionada para a saída padrão.

`asyncio.subprocess.``DEVNULL`

  Valor especial que pode ser usado como argumento stdin, stdout ou stderr para funções de criação de processos. Ele indica que o arquivo especial `os.devnull` será usado para o fluxo de subprocesso correspondente.

## Interagindo com Subprocesso

Ambas as funções `create_subprocess_exec()` e `create_subprocess_shell()` retornam instâncias da classe Process. Process é um wrapper de alto nível que permite a comunicação com subprocessos e observar eles serem completados.

class `asyncio.subprocess.``Process`

  Um objeto que envolve processos do sistema operacional criados pelas funções `create_subprocess_exec()` e `create_subprocess_shell()`.

  Esta classe é projetada para ter uma API similar a classe `subprocess.Popen`, mas existem algumas diferenças notáveis:

  - ao contrário de Popen, Instâncias de Process não tem um equivalente ao método `poll()`;

  - os métodos `communicate()` e `wait()` não tem um parâmetro timeout: utilize a função `wait_for()`;

  - o método `Process.wait()` é assíncrono, enquanto que o método `subprocess.Popen.wait()` é implementado como um laço bloqueante para indicar que está ocupado;

  - o parâmetro universal_newlines não é suportado.

  Esta classe não é seguro para thread.

  Veja também a seção Subprocesso e Threads.

  coroutine `wait`()

    Aguarda o processo filho encerrar.

    Define e retorna o atributo `returncode`.

    Nota

    Este método pode entrar em deadlock ao usar `stdout=PIPE` ou `stderr=PIPE` e o processo filho gera tantas saídas que ele bloqueia a espera pelo encadeamento de buffer do sistema operacional para aceitar mais dados. Use o método `communicate()` ao usar encadeamentos para evitar essa condição.

  coroutine `communicate`(input=None)

    Interage com processo:

    1. envia dados para stdin (se input for diferente de `None`);

    2. lê dados a partid de stdout e stderr, até que EOF (fim do arquivo) seja atingido;

    3. aguarda o processo encerrar.

    O argumento opcional input é a informação (objeto `bytes`) que será enviada para o processo filho.

    Retorna uma tupla `(stdout_data, stderr_data)`.

    Se qualquer exceção `BrokenPipeError` ou `ConnectionResetError` for levantada ao escrever input em stdin, a exceção é ignorada. Esta condição ocorre quando o processo encerra antes de todos os dados serem escritos em stdin.

    Se for desejado enviar dados para o stdin do processo, o mesmo precisa ser criado com `stdin=PIPE`. De forma similar, para obter qualquer coisa além de `None` na tupla resultante, o processo precisa ser criado com os argumentos `stdout=PIPE` e/ou `stderr=PIPE`.

    Perceba que, os dados lidos são armazenados em um buffer na memória, então não use este método se o tamanho dos dados é grande ou ilimitado.

  `send_signal`(signal)

    Envia o sinal signal para o processo filho.

    Nota

    No Windows, `SIGTERM` é um apelido para `terminate()`. `CTRL_C_EVENT` e `CTRL_BREAK_EVENT` podem ser enviados para processos iniciados com um parâmetro creationflags, o qual inclui `CREATE_NEW_PROCESS_GROUP`.

  `terminate`()

    Interrompe o processo filho.

    Em sistemas POSIX este método envia `signal.SIGTERM` para o processo filho.

    No Windows a função `TerminateProcess()` da API Win32 é chamada para interromper o processo filho.

  `kill`()

    Mata o (processo) filho

    Em sistemas POSIX este método envia `SIGKILL` para o processo filho.

    No Windows este método é um atalho para `terminate()`.

  `stdin`

    Fluxo de entrada padrão (`StreamWriter`) ou `None` se o processo foi criado com `stdin=None`.

  `stdout`

    Fluxo de saída padrão (`StreamReader`) ou `None` se o processo foi criado com `stdout=None`.

  `stderr`

    Erro de fluxo padrão (`StreamReader`) ou `None` se o processo foi criado com `stderr=None`.

  Aviso

  Use o método `communicate()` ao invés de `process.stdin.write()`, `await process.stdout.read()` ou `await process.stderr.read`. Isso evita deadlocks devido a fluxos pausando a leitura ou escrita, e bloqueando o processo filho.

  `pid`

    Número de identificação do processo (PID).

    Perceba que para processos criados pela função `create_subprocess_shell()` function, este atributo é o PID do console gerado.

  `returncode`

    Retorna o código do processo quando o mesmo terminar.

    Um valor `None` indica que o processo ainda não terminou.

    Um valor negativo `-N` indica que o filho foi terminado pelo sinal `N` (POSIX apenas).

### Subprocesso e Threads

Standard asyncio event loop supports running subprocesses from different threads, but there are limitations:

- An event loop must run in the main thread.

- The child watcher must be instantiated in the main thread before executing subprocesses from other threads. Call the `get_child_watcher()` function in the main thread to instantiate the child watcher.

Note that alternative event loop implementations might not share the above limitations; please refer to their documentation.

Ver também

A seção Concorrência e multithreading em asyncio.

### Exemplos

Um exemplo de uso da classe `Process` para controlar um subprocesso e a classe `StreamReader` para ler a partir da sua saída padrão.

O subprocesso é criado pela função `create_subprocess_exec()`:

    import asyncio
    import sys

    async def get_date():
        code = 'import datetime; print(datetime.datetime.now())'

        # Create the subprocess; redirect the standard output
        # into a pipe.
        proc = await asyncio.create_subprocess_exec(
            sys.executable, '-c', code,
            stdout=asyncio.subprocess.PIPE)

        # Read one line of output.
        data = await proc.stdout.readline()
        line = data.decode('ascii').rstrip()

        # Wait for the subprocess exit.
        await proc.wait()
        return line

    if sys.platform == "win32":
        asyncio.set_event_loop_policy(
            asyncio.WindowsProactorEventLoopPolicy())

    date = asyncio.run(get_date())
    print(f"Current date: {date}")

Veja também o mesmo exemplo escrito usando APIs de baixo nível.