Документация Python неофициальный перевод
Содержание страницы

17.5. popen2 – Подпроцессы с доступными потоками ввода-выводаpopen2 – Subprocesses with accessible I/O streams

Устарело с версии 2.6: Этот модуль устарел. Используйте модуль subprocess. Обратите особое внимание на раздел Замена старых функций модулем subprocess.

Этот модуль позволяет запускать процессы и подключаться к их каналам ввода/вывода/ошибок, а также получать коды возврата в Unix и Windows.

Модуль subprocess предоставляет более мощные средства для порождения новых процессов и получения их результатов. Использование модуля subprocess предпочтительнее использования модуля popen2.

Основной интерфейс, предоставляемый этим модулем, – это три порождающие функции. Для каждой из них, если указан bufsize, он задает размер буфера для каналов ввода-вывода. mode, если указан, должен быть строкой 'b' или 't'; в Windows это необходимо для определения, должны ли файловые объекты открываться в двоичном или текстовом режиме. Значение по умолчанию для mode't'.

В Unix cmd может быть последовательностью, и в этом случае аргументы будут переданы напрямую программе без участия оболочки (как с os.spawnv()). Если cmd – строка, она будет передана оболочке (как с os.system()).

Единственный способ получить коды возврата дочерних процессов – использовать методы poll() или wait() классов Popen3 и Popen4; они доступны только в Unix. Эта информация недоступна при использовании функций popen2(), popen3() и popen4() или эквивалентных функций из модуля os. (Обратите внимание, что кортежи, возвращаемые функциями модуля os, находятся в другом порядке, чем те, что возвращаются модулем popen2.)

popen2.popen2(cmd[, bufsize[, mode]])

Выполняет cmd как подпроцесс. Возвращает файловые объекты (child_stdout, child_stdin).

popen2.popen3(cmd[, bufsize[, mode]])

Выполняет cmd как подпроцесс. Возвращает файловые объекты (child_stdout, child_stdin, child_stderr).

popen2.popen4(cmd[, bufsize[, mode]])

Выполняет cmd как подпроцесс. Возвращает файловые объекты (child_stdout_and_stderr, child_stdin).

Новое в версии 2.0.

В Unix также доступен класс, определяющий объекты, возвращаемые порождающими функциями. Они не используются в реализации для Windows и недоступны на этой платформе.

class popen2.Popen3(cmd[, capturestderr[, bufsize]])

Этот класс представляет дочерний процесс. Обычно экземпляры Popen3 создаются с помощью порождающих функций popen2() и popen3(), описанных выше.

Если для создания объектов Popen3 не используются вспомогательные функции, параметр cmd – это команда оболочки для выполнения в подпроцессе. Флаг capturestderr, если true, указывает, что объект должен захватывать стандартный вывод ошибок дочернего процесса. По умолчанию false. Если указан параметр bufsize, он задает размер буферов ввода-вывода для дочернего процесса.

class popen2.Popen4(cmd[, bufsize])

Аналогично Popen3, но всегда захватывает стандартную ошибку в тот же файловый объект, что и стандартный вывод. Обычно создаются с помощью popen4().

Новое в версии 2.0.

17.5.1. Объекты Popen3 и Popen4Popen3 and Popen4 Objects

Экземпляры классов Popen3 и Popen4 имеют следующие методы:

Popen3.poll()

Возвращает -1, если дочерний процесс еще не завершился, или его код состояния (см. wait()) в противном случае.

Popen3.wait()

Ожидает завершения дочернего процесса и возвращает его код состояния. Код состояния содержит как код возврата процесса, так и информацию о том, завершился ли он с помощью системного вызова exit() или был завершен сигналом. Функции для интерпретации кода состояния определены в модуле os; см. раздел Управление процессами для семейства функций W*().

Также доступны следующие атрибуты:

Popen3.fromchild

Файловый объект, предоставляющий вывод от дочернего процесса. Для экземпляров Popen4 он будет предоставлять как стандартный вывод, так и стандартный поток ошибок.

Popen3.tochild

Файловый объект, предоставляющий ввод в дочерний процесс.

Popen3.childerr

Файловый объект, предоставляющий вывод ошибок от дочернего процесса, если для конструктора capturestderr было true, в противном случае None. Для экземпляров Popen4 это всегда будет None.

Popen3.pid

PID дочернего процесса.

17.5.2. Проблемы управления потокомFlow Control Issues

При работе с любой формой межпроцессного взаимодействия необходимо тщательно продумывать управление потоком. Это относится и к файловым объектам, предоставляемым этим модулем (или эквивалентами из модуля os).

При чтении вывода из дочернего процесса, который записывает много данных в стандартную ошибку, в то время как родитель читает из стандартного вывода дочернего процесса, может возникнуть взаимоблокировка. Аналогичная ситуация может возникнуть и при других комбинациях чтения и записи. Основные факторы: один процесс записывает более _PC_PIPE_BUF байт в блокирующем режиме, в то время как другой процесс читает из первого, также в блокирующем режиме.

Есть несколько способов справиться с этой ситуацией.

Самое простое изменение приложения во многих случаях – следовать этой модели в родительском процессе:

import popen2

r, w, e = popen2.popen3('python slave.py')
e.readlines()
r.readlines()
r.close()
e.close()
w.close()

с таким кодом в дочернем процессе:

import os
import sys

# обратите внимание, что каждый из этих операторов print
# записывает одну длинную строку

print >>sys.stderr, 400 * 'this is a test\n'
os.close(sys.stderr.fileno())
print >>sys.stdout, 400 * 'this is another test\n'

Учитывайте, что sys.stderr необходимо закрыть после записи всех данных, иначе readlines() не вернёт управление. Также обратите внимание, что следует использовать os.close(), поскольку sys.stderr.close() не закроет stderr (в противном случае присваивание sys.stderr закроет его без предупреждения, и дальнейшие ошибки не будут выведены).

Приложениям, которым требуется более общий подход, следует интегрировать ввод-вывод через каналы в свои select() циклы или использовать отдельные потоки для чтения каждого из файлов, предоставленных используемой popen*() функцией или Popen* классом.

См. также

Модуль subprocess

Модуль для порождения и управления подпроцессами.