Я запускаю простой сценарий Python 3.6 через подпроцесс другого сценария Python 3.6. Я захватываю SIGINT в исходном процессе, чтобы передать его подпроцессу. Это просто для тестирования модуля, который в конечном итоге будет обертывать другие вещи, но это не слишком важно.
Когда я запускаю подпроцесс без оболочки и отправляю SIGINT, чтобы остановить его, вывод иногда полностью отсутствует трассировка из подпроцесса, в других случаях она просто содержит строку Traceback (most recent call last):
, а иногда она содержит полную трассировку.
Я использую Popen, но я также подтвердил, что то же самое происходит при использовании функции communication () или check_output & co.
Однако вот неприятность: если я установил shell=True
, я всегда получаю полную трассировку при отправке SIGINT в подпроцесс.
Минимальный пример
producer.py
#!/usr/bin/env python3
import sys
import signal
import time
for number in range(100):
sys.stderr.write(str(number) + 'this is line ' + str(number) + '\n')
time.sleep(0.01)
sys.stderr.flush()
consumer.py
import subprocess
import signal
import sys
import time
process = subprocess.Popen(['./producer.py'],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
bufsize=1,
#shell=True,
encoding="latin-1",
universal_newlines=True)
def stop_process(a,b):
process.send_signal(signal.SIGINT)
old_handler = signal.signal(signal.SIGINT, stop_process)
s, e = process.communicate()
print(s)
print('-----')
print(e)
Попробуйте запустить python3 consumer.py
и в любой момент нажать CTRL + C . Если вы попробуете несколько раз, вы увидите различные варианты поведения, которые я перечислил. Теперь попробуйте еще раз после раскомментирования shell=True
в потребителе, и вы должны каждый раз получать полную трассировку.
Кто-нибудь знает, почему это так? Я подозреваю python махинаций переводчика, но я хотел бы понять, что происходит.