Spec-Zone.ru › Python 3.6

Подпроцессы

Исходный код: Lib/asyncio/subprocess.py

18.5.6.1. Цикл обработки событий Windows

В Windows по умолчанию используется цикл обработки событий SelectorEventLoop, который не поддерживает подпроцессы. Вместо него следует использовать ProactorEventLoop. Пример использования в Windows:

import asyncio, sys

if sys.platform == 'win32':
    loop = asyncio.ProactorEventLoop()
    asyncio.set_event_loop(loop)

См. также

Доступные циклы обработки событий и Поддержка платформ.

18.5.6.2. Создание подпроцесса: API высокого уровня с использованием Process

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

Создаёт подпроцесс.

Параметр limit задаёт предел буфера, передаваемый в StreamReader. Другие параметры см. в AbstractEventLoop.subprocess_exec().

Возвращает экземпляр Process.

Эта функция является корутиной.

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

Выполняет командную строку cmd.

Параметр limit задаёт предел буфера, передаваемый в StreamReader. Другие параметры см. в AbstractEventLoop.subprocess_shell().

Возвращает экземпляр Process.

Приложения несут ответственность за правильное экранирование пробелов и метасимволов в командных строках, чтобы избежать уязвимостей типа «всплеск оболочки». Функцию shlex.quote() можно использовать для правильного экранирования пробелов и метасимволов оболочки в строках, которые будут использоваться для построения команд оболочки.

Эта функция является корутиной.

Используйте методы AbstractEventLoop.connect_read_pipe() и AbstractEventLoop.connect_write_pipe() для подключения каналов.

18.5.6.3. Создание подпроцесса: API низкого уровня с использованием subprocess.Popen

Асинхронное выполнение подпроцессов с использованием модуля subprocess.

coroutine AbstractEventLoop.subprocess_exec(protocol_factory, *args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)

Создаёт подпроцесс из одной или нескольких строковых аргументов (строки или байтовые строки, закодированные в кодировку файловой системы), где первая строка указывает программу для выполнения, а остальные строки — аргументы программы. (Таким образом, вместе аргументы строк образуют значение sys.argv программы, предполагая, что это скрипт Python.) Это аналогично стандартному библиотечному классу subprocess.Popen, вызываемому с параметром shell=False и списком строк, переданных в качестве первого аргумента; однако, где Popen принимает один аргумент, который является списком строк, subprocess_exec() принимает несколько строковых аргументов.

protocol_factory должен создавать подкласс класса asyncio.SubprocessProtocol.

Другие параметры:

  • stdin: либо объект, подобный файлу, представляющий канал, подключаемый к стандартному вводу подпроцесса с помощью connect_write_pipe(), либо константа subprocess.PIPE (по умолчанию). По умолчанию создаётся и подключается новый канал.
  • stdout: либо объект, подобный файлу, представляющий канал, подключаемый к стандартному выводу подпроцесса с помощью connect_read_pipe(), либо константа subprocess.PIPE (по умолчанию). По умолчанию создаётся и подключается новый канал.
  • stderr: либо объект, подобный файлу, представляющий канал, подключаемый к стандартному ошибочному выводу подпроцесса с помощью connect_read_pipe(), либо константа subprocess.PIPE (по умолчанию) или subprocess.STDOUT. По умолчанию создаётся и подключается новый канал. Когда задано subprocess.STDOUT, стандартный вывод ошибок подпроцесса подключается к тому же каналу, что и стандартный вывод.
  • Все остальные ключевые аргументы передаются в subprocess.Popen без интерпретации, за исключением bufsize, universal_newlines и shell, которые вообще не следует указывать.

Возвращает пару (transport, protocol), где transport — экземпляр BaseSubprocessTransport.

Этот метод является корутиной.

См. конструктор класса subprocess.Popen для параметров.

coroutine AbstractEventLoop.subprocess_shell(protocol_factory, cmd, *, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)

Создаёт подпроцесс из cmd, которое является строкой или байтовой строкой, закодированной в кодировку файловой системы, с использованием синтаксиса «оболочки» платформы. Это аналогично стандартному библиотечному классу subprocess.Popen, вызываемому с параметром shell=True.

protocol_factory должен создавать подкласс класса asyncio.SubprocessProtocol.

См. subprocess_exec() для получения дополнительной информации об оставшихся аргументах.

Возвращает пару (transport, protocol), где transport — экземпляр BaseSubprocessTransport.

Приложения несут ответственность за правильное экранирование пробелов и метасимволов в командных строках, чтобы избежать уязвимостей типа «всплеск оболочки». Функцию shlex.quote() можно использовать для правильного экранирования пробелов и метасимволов оболочки в строках, которые будут использоваться для построения команд оболочки.

Этот метод является корутиной.

См. также

Методы AbstractEventLoop.connect_read_pipe() и AbstractEventLoop.connect_write_pipe().

18.5.6.4. Константы

asyncio.subprocess.PIPE

Специальное значение, которое может использоваться в качестве аргумента stdin, stdout или stderr для create_subprocess_shell() и create_subprocess_exec() и указывает на то, что должен быть открыт канал к стандартному потоку.

END_OF_DOCUMENT_MARKER
asyncio.subprocess.STDOUT

Специальное значение, которое можно использовать в качестве аргумента stderr для create_subprocess_shell() и create_subprocess_exec() и указывает, что стандартная ошибка должна попадать в тот же обработчик, что и стандартный вывод.

asyncio.subprocess.DEVNULL

Специальное значение, которое может быть использовано в качестве аргумента stdin, stdout или stderr для create_subprocess_shell() и create_subprocess_exec() и указывает, что будет использован специальный файл os.devnull.

18.5.6.5. Процесс

class asyncio.subprocess.Process

Подпроцесс, созданный функцией create_subprocess_exec() или create_subprocess_shell().

API класса Process разработан так, чтобы быть похожим на API класса subprocess.Popen, но есть некоторые различия:

  • Нет явного метода poll()
  • Методы communicate() и wait() не принимают параметр timeout: используйте функцию wait_for()
  • Параметр universal_newlines не поддерживается (поддерживаются только байтовые строки)
  • Метод wait() класса Process является асинхронным, в то время как метод wait() класса Popen реализован как цикл с ожиданием.

Этот класс не потокобезопасен. Смотрите также раздел Подпроцессы и потоки.

coroutine wait()

Ожидает завершения дочернего процесса. Устанавливает и возвращает атрибут returncode.

Этот метод является генератором.

Примечание

Это приведет к тупику при использовании stdout=PIPE или stderr=PIPE и дочерний процесс генерирует достаточно вывода в канал, так что он блокируется, ожидая, пока буфер канала ОС примет больше данных. Используйте метод communicate() при использовании каналов, чтобы избежать этого.

coroutine communicate(input=None)

Взаимодействие с процессом: Отправка данных в stdin. Чтение данных из stdout и stderr до тех пор, пока не будет достигнут конец файла. Ожидание завершения процесса. Необязательный аргумент input должен содержать данные, которые будут отправлены дочернему процессу, или None, если данные не должны отправляться. Тип input должен быть байтовым.

Метод communicate() возвращает кортеж (stdout_data, stderr_data).

Если при записи input в stdin возникает исключение BrokenPipeError или ConnectionResetError, оно игнорируется. Это происходит, когда процесс завершается до того, как все данные будут записаны в stdin.

Обратите внимание, что если вы хотите отправлять данные в stdin процесса, вам нужно создать объект Process с stdin=PIPE. Аналогично, чтобы получить что-либо, кроме None в кортеже результата, вам также нужно указать stdout=PIPE и/или stderr=PIPE.

Этот метод является генератором.

Примечание

Считанные данные буферизуются в памяти, поэтому не используйте этот метод, если размер данных большой или неограничен.

Изменено в версии 3.4.2: Метод теперь игнорирует BrokenPipeError и ConnectionResetError.

send_signal(signal)

Отправляет сигнал signal дочернему процессу.

Примечание

В Windows SIGTERM является псевдонимом для terminate(). CTRL_C_EVENT и CTRL_BREAK_EVENT могут быть отправлены процессам, запущенным с параметром creationflags, который включает CREATE_NEW_PROCESS_GROUP.

terminate()

Останавливает дочерний процесс. В системах POSIX метод отправляет signal.SIGTERM дочернему процессу. В Windows вызывается функция Win32 API TerminateProcess() для остановки дочернего процесса.

kill()

Уничтожает дочерний процесс. В системах POSIX функция отправляет SIGKILL дочернему процессу. В Windows kill() является псевдонимом для terminate().

stdin

Поток стандартного ввода (StreamWriter), None если процесс был создан с stdin=None.

stdout

Поток стандартного вывода (StreamReader), None если процесс был создан с stdout=None.

stderr

Поток стандартной ошибки (StreamReader), None если процесс был создан с stderr=None.

Предупреждение

Используйте метод communicate() вместо .stdin.write, .stdout.read или .stderr.read для предотвращения тупиков из-за приостановки чтения или записи потоков, блокирующих дочерний процесс.

pid

Идентификатор процесса.

Обратите внимание, что для процессов, созданных функцией create_subprocess_shell(), этот атрибут — идентификатор процесса созданного оболочки.

returncode

Код возврата процесса при завершении. Значение None указывает, что процесс еще не завершен.

Отрицательное значение -N указывает, что дочерний процесс был завершен сигналом N (только Unix).

18.5.6.6. Подпроцессы и потоки

asyncio поддерживает запуск подпроцессов из разных потоков, но есть ограничения:

  • Цикл событий должен работать в главном потоке
  • Наблюдатель за дочерними процессами должен быть инициализирован в главном потоке, до запуска подпроцессов из других потоков. Вызовите функцию get_child_watcher() в главном потоке для инициализации наблюдателя за дочерними процессами.

Класс asyncio.subprocess.Process не потокобезопасен.

См. также

Раздел Асинхронность и многопоточность в asyncio.

18.5.6.7. Примеры использования подпроцессов

18.5.6.7.1. Подпроцесс с использованием транспорта и протокола

Пример протокола подпроцесса, используемого для получения вывода подпроцесса и ожидания завершения работы подпроцесса. Подпроцесс создается методом AbstractEventLoop.subprocess_exec():

import asyncio
import sys

class DateProtocol(asyncio.SubprocessProtocol):
    def __init__(self, exit_future):
        self.exit_future = exit_future
        self.output = bytearray()

    def pipe_data_received(self, fd, data):
        self.output.extend(data)

    def process_exited(self):
        self.exit_future.set_result(True)

@asyncio.coroutine
def get_date(loop):
    code = 'import datetime; print(datetime.datetime.now())'
    exit_future = asyncio.Future(loop=loop)

    # Create the subprocess controlled by the protocol DateProtocol,
    # redirect the standard output into a pipe
    create = loop.subprocess_exec(lambda: DateProtocol(exit_future),
                                  sys.executable, '-c', code,
                                  stdin=None, stderr=None)
    transport, protocol = yield from create

    # Wait for the subprocess exit using the process_exited() method
    # of the protocol
    yield from exit_future

    # Close the stdout pipe
    transport.close()

    # Read the output which was collected by the pipe_data_received()
    # method of the protocol
    data = bytes(protocol.output)
    return data.decode('ascii').rstrip()

if sys.platform == "win32":
    loop = asyncio.ProactorEventLoop()
    asyncio.set_event_loop(loop)
else:
    loop = asyncio.get_event_loop()

date = loop.run_until_complete(get_date(loop))
print("Current date: %s" % date)
loop.close()

18.5.6.7.2. Подпроцесс с использованием потоков

Пример использования класса Process для управления подпроцессом и класса StreamReader для чтения со стандартного вывода. Подпроцесс создается функцией create_subprocess_exec():

import asyncio.subprocess
import sys

@asyncio.coroutine
def get_date():
    code = 'import datetime; print(datetime.datetime.now())'

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

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

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

if sys.platform == "win32":
    loop = asyncio.ProactorEventLoop()
    asyncio.set_event_loop(loop)
else:
    loop = asyncio.get_event_loop()

date = loop.run_until_complete(get_date())
print("Current date: %s" % date)
loop.close()

© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.6/library/asyncio-subprocess.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API