Имитация прерывания клавиатуры Ctrl-C в Python при работе в Linux

Я работаю над некоторыми сценариями (в компании, в которой я работаю), которые загружаются/выгружаются в гипервизоры для запуска фрагмента кода при возникновении события. Единственный способ фактически выгрузить скрипт-это нажать Ctrl-C. Я пишу функцию в Python, которая автоматизирует процесс

как только он видит строку "done" в выводе программы он должен убить vprobe. Я использую subprocess.Popen выполнить команду:

lineList = buff.readlines()
cmd = "vprobe /vprobe/myhello.emt"
p = subprocess.Popen(args = cmd, shell=True,stdout = buff, universal_newlines = True,preexec_fn=os.setsid)
while not re.search("done",lineList[-1]):
        print "waiting"
os.kill(p.pid,signal.CTRL_C_EVENT)

As вы можете видеть, я пишу вывод в buff файловый дескриптор открыт в режиме чтения+записи. Я проверяю последнюю строку; если она имеет 'done', Я убью его. К сожалению,CTRL_C_EVENT действует только для Windows. Что я могу сделать для Linux?

3 ответов


Я думаю, вы можете просто отправить эквивалент Linux,signal.SIGINT (сигнал прерывания).

(Edit: раньше у меня было что-то, препятствующее использованию этой стратегии для управления подпроцессами, но при более тщательном чтении это звучит так, как будто вы уже решили, что вам нужен control-C в этом конкретном случае... Итак, SIGINT должен это сделать.)


в Linux прерывание клавиатуры Ctrl-C может быть отправлено программно процессу с помощью Popen.send_signal(сигнал.SIGINT) функция. Например

import subprocess
import signal

..
process = subprocess.Popen(..)
..
process.send_signal(signal.SIGINT)
..

Не используйте Popen.communicate () для блокировки команд..


может быть, я что-то неправильно понял, но так, как вы это делаете, трудно получить желаемый результат.

все buff есть запросы, а затем использовать его в контексте Popen() и тогда вы надеетесь, что maciv lineList заполняется.

что вы, вероятно, хотите что-то вроде

logfile = open("mylogfile", "a")
p = subprocess.Popen(['vprobe', '/vprobe/myhello.emt'], stdout=subprocess.PIPE,  buff, universal_newlines=True, preexec_fn=os.setsid)
for line in p.stdout:
    logfile.write(line)
    if re.search("done", line):
        break
    print "waiting"
os.kill(p.pid, signal.CTRL_C_EVENT)

это дает вам конец трубы, питаемый вашим vprobe скрипт, который вы можете прочитать линейно и действовать соответствующим образом на найденном выходе.