Я пишу скрипт, который должен запускать интерактивную оболочку сторонней программы из python в linux (сторонней программой является Stata). Целью скрипта является управление stdin и stdout интерактивной оболочки, чтобы я мог получить к нему доступ из редактора и других скриптов.
При запуске из оболочки Linux, Stata запускает интерактивную оболочку, в которой вы можете запускать команды Stata. Когда я нажимаю control + C или другим способом отправляю сигнал SIGINT в Stata, он прекращает выполнение текущей команды и возвращается в интерактивную оболочку, но не останавливает процесс Stata. Я хочу повторить это поведение для Stata, запущенной из python.
Когда я отправляю сигнал SIGINT процессу Stata, запущенному из python, он прерывает процесс, а не останавливает выполнение текущей команды.
Поведение в оболочке:
> /usr/local/stata14/stata
(...other stuff...)
. forval i = 1/100000 {
2. sleep 10
3. di "`i'"
4. }
1
2
3
4
(I hit CTRL+C)
--Break--
r(1);
.
Следующая программа на Python запускает Stata из Python:
def handler(signum, frame):
stata.send_signal(signal.SIGINT)
signal.signal(signal.SIGINT, handler)
stata = subprocess.Popen(["/usr/local/stata14/stata"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=os.setpgrp)
(... other stuff hat handles forwarding stata.stdout to sys.stdout in a separate thread...)
while true:
time.sleep(0.1)
userinput = raw_input(". ")
print(userinput, file=stata.stdin)
stata.stdin.flush()
print(stata.poll())
с тем же циклом for, запущенным в подпроцессе, выдает:
> /usr/local/stata14/stata
. forval i = 1/100000 {
2. sleep 10
3. di "`i'"
4. }
1
2
3
4
-2
-2
-2
и любая дальнейшая попытка записи в stata.stdin приводит к
print(userinput, file=stata.stdin)
IOError: [Errno 32] Broken pipe
Кто-нибудь понимает, почему это происходит? Я уже пытался использовать подпроцесс. Открыть с shell = True. В этом случае Popen запускает процесс sh и процесс Stata. Если я отправляю SIGINT процессу sh, ничего не происходит. Если я отправлю его в Stata, возникнет та же проблема, что и с shell = False.
Заранее спасибо.