Подпроцесс Python. Откройте PIPE и SIGPIPE

Пока я просматривал сообщения, я наткнулся на этот пример ниже, здесь говорится proc1.stdout.close() необходимо вызвать для соответствующего выхода proc1, генерируя SIGPIPE,

import subprocess

proc1 = subprocess.Popen(['ps', 'cax'], stdout=subprocess.PIPE)
proc2 = subprocess.Popen(['grep', 'python'], stdin=proc1.stdout,
                         stdout=subprocess.PIPE, stderr=subprocess.PIPE)

proc1.stdout.close() # Allow proc1 to receive a SIGPIPE if proc2 exits.
out, err = proc2.communicate()
print('out: {0}'.format(out))
print('err: {0}'.format(err))

Однако я не совсем уверен в этом. Пожалуйста, исправьте мое понимание.

  1. SIGPIPE происходит, когда PIPE пытается написать в закрытое PIPE,
  2. писатель PIPE является proc1"s stdout и читатель PIPE является proc2"s stdin,
  3. proc1 выйдет когда proc2 выход и proc1 пытается записать данные в proc2"s stdin PIPE, так как
    • proc2"s stdin PIPE закрыто, когда proc2 выход
    • SIGPIPE случиться в proc1 так как proc1 пытается написать в закрытое proc2"s stdin PIPE,

Из моего понимания, SIGPIPE случится и proc1 выйдет, независимо от закрытия proc1"s stdout,

Что мне не хватает?


редактировать

Прочитав пост от комментария @unutbu......

Думаю скопированный дескриптор файла (proc1.stdout) это писатель ТРУБЫ, а не читатель ТРУБЫ. таким образом, есть два устройства записи PIPE и одно устройство чтения PIPE, соединенные друг с другом.

Следовательно, SIGPIPE будет создан, когда proc2 выход, потому что proc2 только один процесс, который имеет читатель PIPE(будет закрыт, когда proc2 выход).

Тем не менее, вышеприведенный пост, кажется, говорит, что есть две читающие ТРУБЫ, копируя proc1.stdout так SIGPIPE не будет генерироваться даже после proc2 выход, потому что есть еще один читатель PIPE открыт. ниже часть сообщения.

Поэтому, немедленно закрыв p1.stdout, вы гарантируете, что единственное оставшееся чтение дескриптора файла из dmesg stdout - это процесс grep, и если этот процесс завершится, dmesg получит SIGPIPE.

Я не говорю, что сообщение неправильное, но я просто хочу исправить свое понимание. Заранее спасибо.

1 ответ

Решение
proc1 = subprocess.Popen(['ps', 'cax'], stdout=subprocess.PIPE)

создает эту трубу между родительским процессом и proc1:

|        |         |       |
| parent |-<-----<-| proc1 |                   
|        | ^       |       |
           |                     
       p1.stdout   

p1.stdout это то, что родитель прочитал бы для получения (stdout) вывода из proc1,

proc2 = subprocess.Popen(['grep', 'python'], stdin=proc1.stdout,
                         stdout=subprocess.PIPE, stderr=subprocess.PIPE)

подключает копию канала от proc1 к proc2:

|        |         |       |         |       |
| parent |-<-----<-| proc1 |->----->-| proc2 | 
|        |         |       |         |       |

По телефону p1.stdout.close()закрываем сторону канала родительских процессов:

|        |         |       |         |       |
| parent |       <-| proc1 |->----->-| proc2 | 
|        |         |       |         |       |

Теперь когда proc2 заканчивается, его сторона трубы тоже закрыта:

|        |         |       |         |       |
| parent |       <-| proc1 |->       | proc2 | 
|        |         |       |         |       |

В следующий раз proc1 пытается записать в канал, генерируется сигнал SIGPIPE, который позволяет proc1 прекратить, так как он знает, что никто не слушает на другом конце его каналов.

Другие вопросы по тегам