Подпроцесс 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))
Однако я не совсем уверен в этом. Пожалуйста, исправьте мое понимание.
SIGPIPE
происходит, когдаPIPE
пытается написать в закрытоеPIPE
,- писатель
PIPE
являетсяproc1
"sstdout
и читательPIPE
являетсяproc2
"sstdin
, proc1
выйдет когдаproc2
выход иproc1
пытается записать данные вproc2
"sstdin PIPE
, так какproc2
"sstdin PIPE
закрыто, когдаproc2
выходSIGPIPE
случиться вproc1
так какproc1
пытается написать в закрытоеproc2
"sstdin 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
прекратить, так как он знает, что никто не слушает на другом конце его каналов.