2014-01-03 2 views
1

У меня есть процесс, который записывает непрерывный поток байтов в stdout. У меня есть еще один процесс, который читается с начала первого процесса, а затем заканчивается. Но я обнаружил, что когда второй процесс заканчивается, он закрывает трубу (я думаю), и поэтому процесс 1 останавливается.Подпроцесс python: чтение из трубы без его закрытия

Я попробовал это 2 различными способами:

в оболочке 1:

# make fifo 
mkfifo /tmp/camera 
# stream video from my webcam to the pipe 
ffmpeg -y -f v4l2 -r 10 -i /dev/video0 -f avi /tmp/camera 

в оболочке 2:

# attach to pipe and take a snapshot 
rrmpeg -y -r 1 -f avi -i /tmp/camera -vframes 1 -s 160x120 -f image2 image1.jpg 

Я также попытался это в оболочке 2 с тем же результатом:

tail -f /tmp/camera 

Когда p rocess в shell 2 останавливается, он убивает процесс 1. Почему?

Вторая вещь, которую я попытался было с питона подпроцесса:

from subprocess import Popen, PIPE 
import shlex, time 

stream = Popen(shlex.split("ffmpeg -y -f v4l2 -r 10 -i /dev/video0 -f avi -"), stdout=PIPE) 
while True: 
    time.sleep(3) 
    snap = Popen(shlex.split("rrmpeg -y -r 1 -f avi -i - -vframes 1 -s 160x120 -f image2 image1.jpg"), stdin=stream.stdout) 

Он работает в первый раз через петлю, но когда процесс snap выходит из области видимости, процесс stream умирает.

Есть ли способ прочитать часть потока из процесса 1 без его закрытия?

+0

Я пробовал подход 1, и он работал как шарм. Как и было предложено, я написал сценарий python, который открывает трубку и просто спит навсегда. Затем я снова и снова запускал вторую команду без первого зависания процесса. – thayne

+0

Почти пропустил ваш комментарий. - Ожидалось, что это ниже ответа ... ;-) –

+0

Ничего не закрывает 'stream.stdout' в родительском потоке, поэтому' stream' не должен получать SIGPIPE. – jfs

ответ

1

Да, есть способ, чтобы продолжить писатель трубы навсегда. Для этого, вы должны убедиться, что

  1. по крайней мере один читатель держит трубу открытого (без чтения штрафа) --или--
  2. автора игнорирует SIGPIPE и обрабатывает запись() ошибки хорошо (т. е. пытается снова)

Второй вариант не так прост (без изменения/проверки источника записи) ,

Для первого варианта убедитесь, что ваш первый читатель открывает fifo/pipe, ничего не читает, затем блокирует/спит на что-то навсегда, не умирая.

Пусть любые последующие читатели выполняют свою работу. Они могут открывать fifo (named pipe) или должны быть раздвоены из процесса, имеющего открытый конец чтения (они наследуют filedescriptor).

Этот способ не генерирует SIGPIPE, и write() блокирует запись, как только буфер буфера заполнен.

man 7 pipe говорит вам больше.

(Примечание:.. Некоторые программы могут запутаться, если запись() блокирует неожиданный длинный Например, некоторые приложения, которые регулярно смотрят на стену-часы)

Что касается «Когда процесс в скорлупе 2 остановки, то убивает процесс 1. Почему?":

Процесс 1, вероятно, был убит SIGPIPE (я не проверял источник), который он получает, когда он пробует write() на трубе без считывателя.

Смежные вопросы