правильная цепочка подпроцессов - PullRequest
7 голосов
/ 11 июля 2011

У меня есть такая конструкция:

os.mkfifo('pipe.tmp')
enc = Popen(['encoder', '-i', 'pipe.tmp'])
cap = Popen(['capture', '-f', 'pipe.tmp'])

здесь cap - это процесс, который обычно выполняет запись в файл (заданный -f), но я могу заставить его выводить данные на экран, предоставив /dev/stdout в качестве выходного файла. Точно так же enc ожидает чтения из файловоподобного объекта, и я могу получить его для чтения из канала, указав - в качестве входных данных. поэтому вместо использования именованного канала в ОС я подумал, что специальный файл может не понадобиться, я могу использовать такой канал без имени, как этот ...

cap = Popen(['capture', '-f', '/dev/stdout'], stdout=PIPE)
enc = Popen(['encoder', '-i', '-'], stdin=cap.stdout)
cap.stdout.close()

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

  1. /dev/stdout, с которым cap разговаривает, отличается от фактического стандартного вывода в ОС? то есть с входным каналом - в enc я получу чистый канал данных между этими двумя процессами, даже если другие процессы переписываются с / dev / stdout в ОС?
  2. Будут ли существенные различия в поведении с блокировкой / очередью? я думаю, что в моем первом примере именованный канал будет буферизован 4096 байтами и будет блокироваться с обоих концов, если cap / enc не достаточно быстро пишет / читает, но исправьте меня, если я ошибаюсь.
  3. Требуется ли какой-либо особый порядок появления или прекращения, или какие-либо другие ошибки, о которых я должен знать?

1 Ответ

1 голос
/ 11 июля 2011
  1. / dev / stdout дает вам стандартный вывод для текущего процесса, так что вам должно быть хорошо его использовать.(в действительности нет ничего «глобального» в отношении / dev / stdout)
  2. Размер fifo в первом примере зависит от конфигурации вашей системы (я не уверен, как это изменить).Но subprocess.Popen позволяет вам определять размер буфера для его операций ввода-вывода, так что вы должны быть в состоянии настроить это. Обновление: Проведя небольшое исследование, я обнаружил, что существует ограничение в 64 КБ для каналов, на которое не влияет аргумент bufsize.Не уверен, как обойти это (кроме как читать чаще и обрабатывать буферизацию вручную)
  3. Для вашего второго примера, похоже, что вы должны начать в том порядке, который вы дали, так как вам нужен cap.stdoutбыть доступным перед запускомВ качестве альтернативы, вы можете оставить два процесса отключенными и обрабатывать связь между ними вручную.
...