Piped Python скрипт занимает 100% процессора при чтении из сломанной трубы
У меня есть два скрипта Python, запущенных на машине Ubuntu Linux. Первый отправляет все свои выходные данные в stdout, второй читает из stdin. Они соединены простой трубой, то есть примерно так:
./step1.py <some_args> | ./step2.py <some_other_args>
То, что делает step2, заключается в том, что он читает входные строки в бесконечном цикле и обрабатывает их:
while True:
try:
l = sys.stdin.readline()
# processing here
Step1 время от времени выходит из строя. Когда это происходит (не уверен, что всегда, но, по крайней мере, в нескольких случаях) , то вместо сбоя/остановки Шаг 2 сходит с ума и начинает забирать 100% процессора, пока я вручную не убью его.
Почему это происходит и как я могу сделать шаг 2 более надежным, чтобы он остановился, когда труба сломана?
Спасибо!
2 ответа:
Другие уже объясняли, почему в некоторых случаях вы оказываетесь в бесконечном цикле.
Во втором (читающем) сценарии вы можете использовать идиому:
Таким образом, вы не окажетесь в бесконечном цикле. Кроме того, вы на самом деле не показали, какое исключение вы пытаетесь поймать во втором скрипте, но я предполагаю, что время от времени вы будете испытывать ошибку "сломанной трубы", которую вы можете и должны поймать, как описано здесь: Как обрабатывать сломанную трубу (SIGPIPE) в в Python?for line in sys.stdin: process(line)
Тогда вся схема могла бы выглядеть так:
try: for line in sys.stdin: process(line) except IOError, e: if e.errno == errno.EPIPE: # EPIPE error else: # Other error
Когда step1 умирает, у вас есть цикл while с попыткой оператора, который вызовет исключение. Таким образом, вы будете постоянно пытаться и терпеть неудачу, используя 100% процессора, поскольку readline не будет блокировать, когда он создает исключение.
Либо добавьте временную задержку к чтению с помощью
time.sleep
, либо, еще лучше, обратите внимание на ошибки, которые выбрасывает readline, и поймайте конкретную ошибку, которая выбрасывается, когда step1 останавливается и выходит из программы вместо того, чтобы пытаться читать из мертвого канала.Вы, вероятно, хотите оператор сна, когда труба пуста, и выход, когда труба умирает, но какое исключение выбрасывается с каким сообщением в каждом случае я оставляю в качестве упражнения для вас, чтобы определить. Оператор сна не нужен в такой ситуации, но он позволит избежать других ситуаций, когда вы можете ударить по высокой загрузке процессора на бесполезной работе.