В чем причина этой ошибки?
Запись в закрытый канал заставляет ОС отправлять SIGPIPE
процессу, вызывающему write
. Это позволяет программе работать как генераторы. Например, следующее не будет выполняться вечно, несмотря на то, что содержит бесконечный l oop, потому что head
выйдет и закроет свой STDIN после чтения десяти строк, что приведет к perl
получению SIGPIPE.
perl -le'1 while print ++$i;' | head
Если сигнал SIGPIPE
игнорируется, системный вызов write
возвратит EPIPE
(Broken pipe). Следующее также не будет работать вечно, потому что print
возвращает ошибку EPIPE
после head
выхода.
perl -le'$SIG{PIPE}="IGNORE"; 1 while print ++$i;' | head
Из-за того, что ваша Python программа получила ошибку EPIPE
, мы выводим два факта:
- Программа Python игнорирует сигналы
SIGPIPE
и - Все дескрипторы конца считывателя канала были закрыты.
Поэтому мы должны спросить себя: почему программа Perl закрывает свой STDIN? очень маловероятно, что его STDIN был закрыт явно. Безусловно, наиболее вероятное объяснение состоит в том, что дочерний процесс был прерван.
"Кто" виноват в этом: ОС / окружение, мой код Python, Perl код?
Это зависит от того, что вызвало выход из программы Perl. Первое, что нужно сделать, это выяснить, какой статус выхода был возвращен дочерним процессом. В зависимости от состояния выхода мы будем знать, был ли
- процесс завершен сигналом,
- процесс завершился с ошибкой или
- процесс завершено успешно.
Если код выхода говорит нам, что процесс был прерван сигналом, код выхода также сообщит нам, каким сигналом. Это может дать нам некоторую информацию. (Это будет самый сложный из трех сценариев ios для отладки.)
Если код завершения сообщает нам, что процесс возвратил ошибку, сам код ошибки может не содержать никакой дополнительной полезной информации, но является ошибкой сообщение, несомненно, было отправлено в STDERR ребенка, чтобы предоставить больше информации.
Если код завершения сообщает нам о успешном завершении процесса, возможно, аргументы или вводимые вами данные не означают того, что вы думаете, что они означают.
Так что не забудьте позвонить tokenizer.wait()
, чтобы получить статус выхода и сохранить его в tokenizer.returncode
. Также обязательно запишите, что отправляется в STDERR.