Подтвердить что ты не робот

Закрытие stdout подпроцесса python с каналами

Вот что я могу прочитать в документации модуля подпроцесса python:

Replacing shell pipeline

    output=`dmesg | grep hda`
    ==>
    p1 = Popen(["dmesg"], stdout=PIPE)
    p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
    p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
    output = p2.communicate()[0]

The p1.stdout.close() call after starting the p2 is important in order for p1
to receive a SIGPIPE if p2 exits before p1.

Я не понимаю, почему нам нужно закрыть p1.stdout после создания p2. Когда точно выполняется p1.stdout.close()? Что происходит, когда p2 никогда не заканчивается? Что происходит, когда не заканчиваются p1 или p2?

4b9b3361

Ответ 1

Из Wikipedia, SIGPIPE - это сигнал, отправленный процессу, когда он пытается записать в канал без процесса, связанного с другим концом.

Когда вы сначала создаете p1 с помощью stdout=PIPE, к каналу подключается один процесс, который является вашим процессом Python, и вы можете прочитать результат с помощью p1.stdout.

При создании p2 с помощью stdin=p1.stdout теперь есть два процесса, связанные с трубой p1.stdout.

Обычно, когда вы запускаете процессы в конвейере, вы хотите, чтобы все процессы завершились, когда какой-либо из процессов завершился. Чтобы это произошло автоматически, вам нужно закрыть p1.stdout, поэтому p2.stdin является единственным процессом, подключенным к этому каналу, таким образом, если p2 завершается, а p1 записывает дополнительные данные в stdout, он получит SIGPIPE, поскольку есть более никаких процессов, связанных с этим каналом.

Ответ 2

ОК, я вижу. p1.stdout закрывается из моего python script, но остается открытым в p2, а затем p1 и p2 обмениваются данными. За исключением случаев, когда p2 уже закрыт, p1 получает SIGPIPE. Правильно ли я?