2012-10-23 7 views
8

Ich arbeite an einigen Skripten (in der Firma, in der ich arbeite), die in Hypervisors geladen/entladen werden, um ein Stück Code bei einem Ereignis auszulösen. Die einzige Möglichkeit, ein Skript tatsächlich zu entladen, ist Ctrl - C. Ich schreibe eine Funktion in Python, die den Prozess automatisiertSimulieren Sie Ctrl-C-Tastatur-Interrupt in Python während der Arbeit in Linux

Sobald es die Zeichenfolge "done" in der Ausgabe des Programms sieht, sollte es die vprobe töten. ich subprocess.Popen bin mit dem Befehl auszuführen:

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) 

Wie Sie sehen können, bin ich die Ausgabe in buff Dateideskriptor in Lese + Schreibmodus geöffnet zu schreiben. Ich überprüfe die letzte Zeile; Wenn es 'done' hat, töte ich es. Leider ist die CTRL_C_EVENT nur für Windows gültig. Was kann ich für Linux tun?

+3

FYI nicht Popen.communicate() zum Blockieren Befehle zur Verfügung: 're.search' mit einem konstanten String kann besser ausgedrückt als', während 'done' nicht in Linelist [-1]: ... ' – nneonneo

+0

Yup, du hast Recht. Vielen Dank. –

Antwort

8

Ich denke, Sie können einfach das Linux-Äquivalent senden, signal.SIGINT (das Interrupt-Signal).

(Edit: Ich habe hier etwas Verwendung dieser Strategie entmutigend Teilprozesse zur Steuerung, sondern vorsichtiger liest es klingt wie Sie bereits Sie in diesem speziellen Fall müssen die Kontrolle-C entschieden hat ... Also, SIGINT sollte es tun.)

+0

hey Andrew. Danke für die Antwort. Aber tatsächlich tötet das SIGINT nur die Unterprozessfunktion, während die vprobe ihre Ausführung fortsetzt. Hast du eine Idee, wie man das auch tötet? Danke –

+1

Nun, wenn es auf Windows funktioniert, dann hoffentlich bedeutet das, dass das Signal an den richtigen Ort geht. Also, versuche etwas Stärkeres. Gib SIGTERM einen Versuch, und wenn das nicht funktioniert, SIGKLL. Wenn SIGKILL nicht funktioniert, dann wird nichts - Sie müssen sich verschiedene Möglichkeiten ansehen, wie Sie mit dem Subprozess umgehen können. –

+0

Haben Sie 'Popen versucht (['vprobe', '/ vprobe/myhello.emt'], shell = False, ...)'? @Core_Dumped – alk

1

Vielleicht verstehe ich etwas falsch, aber so wie Sie es tun, ist es schwierig, das gewünschte Ergebnis zu erzielen.

Was auch immer buff ist, fragen Sie es zuerst, dann verwenden Sie es im Zusammenhang mit Popen() und dann hoffen Sie, dass von Macic lineList sich füllt.

Was möchten Sie wahrscheinlich so etwas wie

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) 

Das gibt Ihnen ein Rohrende von Ihrem vprobe Skript zugeführt, die Sie linewise und handeln entsprechend auf dem gefundenen Ausgabe lesen kann.

+0

Dies ist fast genau das, was ich tun möchte, außer dass ich möchte, dass die Ausgabe auch in einer Datei gedruckt wird (zusammen mit dem Einstieg in das PIPE zu Kontrollzwecken). Wie kann ich das machen? (Ich hoffe ich bin dieses Mal grammatikalisch korrekt :)) –

+0

Ich habe meine Antwort bearbeitet, um einen Weg zu finden, dies zu tun. – glglgl

+0

Der obige Code scheint gut und gut, aber wenn ich das stdout als ein Attribut des Objekts p verwende, gibt es mir Broken PIPE-Fehler. –

3

In Linux kann Ctrl-C-Tastatur-Interrupt programmgesteuert zu einem Prozess mit Popen.send_signal (Signal.SIGINT) -Funktion gesendet werden. Zum Beispiel

import subprocess 
import signal 

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

Sie ..

Verwandte Themen