07 Июл 2023
2 мин
430

Неблокирующее чтение из subprocess.PIPE в Python

Возникают ситуации, когда требуется запустить подпроцесс с помощью модуля subprocess в Python и подключиться к его выходному потоку (стандартный вывод). Иногда

Содержание

Возникают ситуации, когда требуется запустить подпроцесс с помощью модуля subprocess в Python и подключиться к его выходному потоку (стандартный вывод). Иногда возникает необходимость выполнять неблокирующие чтения из этого стандартного вывода. Примером может быть следующий код:

import subprocess
p = subprocess.Popen(['myprogram.exe'], stdout=subprocess.PIPE)
output_str = p.stdout.readline()

В данном случае .readline() будет блокировать выполнение программы, если в стандартный вывод подпроцесса не поступает новых данных. Это может быть нежелательно в некоторых случаях, например, если подпроцесс время от времени генерирует данные, и программа должна обрабатывать их по мере поступления, не останавливая своей работы.

К сожалению, встроенных средств Python для неблокирующего чтения из subprocess.PIPE нет. Однако, это можно обойти с использованием модуля select в Python, который предоставляет функционал для мониторинга изменений состояния файловых дескрипторов.

Вот пример кода, который позволяет выполнять неблокирующие чтения:

import subprocess
import select
import os

p = subprocess.Popen(['myprogram.exe'], stdout=subprocess.PIPE)
while True:
    reads = [p.stdout.fileno()]
    ret = select.select(reads, [], [])

    for fd in ret[0]:
        if fd == p.stdout.fileno():
            output_str = os.read(fd, 1024)

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

Однако, стоит учесть, что этот подход может не работать на всех операционных системах, особенно на Windows. Это связано с тем, что select.select() и os.read() могут не поддерживаться для файловых дескрипторов, не связанных с сокетами. В таком случае, можно рассмотреть использование асинхронного ввода/вывода или многопоточности.

Содержание

Добавить комментарий

Определи профессию по рисунку