Seite 1 von 1

Shell-Programm mit Python steuern

Verfasst: Donnerstag 12. März 2015, 12:46
von Hansen93
Hallo,

ich bin neu hier und habe mich angemeldet, weil ich für mein Problem bislang keine Lösung finden konnte :(
Und zwar arbeite ich mit dem Strömungslöser MISES, der über das Terminal ausgeführt wird. Nun versuche ich aus einem Python-Skript MISES zu starten und Kommandos/Befehle zu übergeben.
Das Starten stellt über os.system("/sw/MISES_2.53/run") kein Problem dar, allerdings erwartet MISES dann eine Eingabe über die Shell. Diese kann ich manuell über die Tastatur zwar eingeben, aber mein Ziel ist es, diese Eingabe im Python-Skript zu automatisieren.
Beispiel(Konnte kein Bild hochladen):
Programm startet und fragt folgendes
Enter ISES file extension
Meine Eingabe soll dann folgende sein
sec01

Dieses sec01 soll quasi vom Skript übernommen werden. Gibt es hier eine Idee für eine Lösung?

Alternativ bin ich auf die Bibliothek pexpect gestoßen. Diese klingt sehr geeignet für meine Aufgabe. Doch ist die Literatur hier sehr sparsam. Ich habe versucht über folgenden Code MISES aufzurufen, was allerdings nicht funktioniert hat:

Code: Alles auswählen

import pexpect
child = pexpect.spawn("/sw/MISES_2.53/run")
child.expect("Enter ISES file Extension")
child.send("Profile_name \n")
Gibt es hier einen entscheidenden Tipp, wie ich mittels spawn ein Programm aufrufen kann ähnlich zum TCL-Skripting? Oder bin ich mit dieser Variante völlig auf dem Holzweg?

Vielen Dank schonmal!

Re: Shell-Programm mit Python steuern

Verfasst: Donnerstag 12. März 2015, 13:41
von BlackJack
@Hansen93: `pexpect` ist da wohl schon das passende Werkzeug. „Hat nicht funktioniert” ist eine Beschreibung mit der man nicht viel anfangen kann. *Was* hat denn nicht funktioniert? Startet das Programm nicht? Explodiert der Rechner?

Das Modul selbst ist ziemlich ausführlich dokumentiert mit teilweise recht umfangreichen Docstrings mit Beispielen.

Re: Shell-Programm mit Python steuern

Verfasst: Donnerstag 12. März 2015, 14:21
von Hansen93
@BlackJack: Danke für die Antwort. Super, dann habe ich zumindest wieder etwas Hoffnung. So wie ich den Code oben aufgeführt habe, startet das Programm nicht. Mir kommt es so vor, als ob Python einfach über die Zeilen hinweg geht.
Ich hatte testweise folgenden Code ausprobiert den ich im Internet gefunden habe:

Code: Alles auswählen

import pexpect
 
child = pexpect.spawn("ls -la /")
while True:
    i = child.expect(['\r\n', pexpect.EOF], timeout = None)
    if i == 0:
        print child.before
    elif i == 1:
        print "--Ende--"
        break
Der funktioniert auch und gibt mir eine Ausgabe. Dann habe ich ls -la / mit meinem Befehl /sw/MISES... ersetzt und siehe da er hat MISES gestartet. Ich kann zwar keine Eingabe bestätigen, aber es startet zumindest das Programm. Mir ist klar, dass das Müll war, aber ich dachte vielleicht so hinter die Funktionsweise zu kommen. Scheinbar hat das hier etwas mit der while Schleife zu tun. Nehme ich sie weg, dann startet MISES wieder nicht. Ich wüsste aber nicht wozu ich in meinem Fall eine Schleife bräuchte bzw. wie diese dann auszusehen hat, damit das Programm läuft.

Re: Shell-Programm mit Python steuern

Verfasst: Donnerstag 12. März 2015, 14:33
von BlackJack
@Hansen93: Das externe Programm wird schon starten, denn das macht ja der `spawn()`-Aufruf. Aber dann muss Dein Programm auch die Ausgabe verarbeiten denn sonst blockiert das externe Programm weil die Ausgaben nicht abgenommen werden. Lass Dir mal ``repr(child.before)`` ausgeben, dann siehst Du was da tatsächlich ausgegeben wird und auf was Du dann matchen musst.

Re: Shell-Programm mit Python steuern

Verfasst: Freitag 13. März 2015, 12:23
von Hansen93
Die Ausgabe über child.before lautet 'None'. Matche ich nun auf 'None' erhalte ich nach kurzer Zeit folgende Ausgabe:

Code: Alles auswählen

Traceback (most recent call last):
  File "./TEST.py", line 9, in <module>
    child.expect('None\n')
  File "/usr/lib/python2.7/dist-packages/pexpect/__init__.py", line 1418, in expect
    timeout, searchwindowsize)
  File "/usr/lib/python2.7/dist-packages/pexpect/__init__.py", line 1433, in expect_list
    timeout, searchwindowsize)
  File "/usr/lib/python2.7/dist-packages/pexpect/__init__.py", line 1535, in expect_loop
    raise TIMEOUT(str(err) + '\n' + str(self))
pexpect.TIMEOUT: Timeout exceeded.
<pexpect.spawn object at 0x7fe0816f6710>
version: 3.2
command: /sw/MISES_2.53/run
args: ['/sw/MISES_2.53/run']
searcher: <pexpect.searcher_re object at 0x7fe0816f6790>
buffer (last 100 chars): ' \r\nEnter ISES file extension\r\n'
before (last 100 chars): ' \r\nEnter ISES file extension\r\n'
after: <class 'pexpect.TIMEOUT'>
match: None
match_index: None
exitstatus: None
flag_eof: False
pid: 24964
child_fd: 3
closed: False
timeout: 30
delimiter: <class 'pexpect.EOF'>
logfile: None
logfile_read: None
logfile_send: None
maxread: 2000
ignorecase: False
searchwindowsize: None
delaybeforesend: 0.05
delayafterclose: 0.1
delayafterterminate: 0.1
Dann habe ich versucht, ob es folgendermaßen funktioniert, führte aber nur zu obigem Ergebnis

Code: Alles auswählen

child.expect('None')
child.expect(' \r\nEnter ISES file extension\r\n')

Re: Shell-Programm mit Python steuern

Verfasst: Freitag 13. März 2015, 12:40
von BlackJack
@Hansen93: Die Ausgabe lautet sehr wahrscheinlich nicht ``'None'`` sondern nur ``None``. Eine Zeichenkette mit den Zeichen 'N', 'o', 'n', 'e' ist etwas anderes als der Wert `None`:

Code: Alles auswählen

In [14]: 'None' == None
Out[14]: False

In [15]: type('None')
Out[15]: str

In [16]: type(None)
Out[16]: NoneType
Wenn Du auf die Zeile mit dem Inhalt 'None\n' wartest, dann wartest Du natürlich ewig weil das externe Programm die nicht ausgibt.

Auf 'Enter ISES file extension\r\n' müsste man also warten. Und beim senden der Eingabe würde ich dann auch '\r\n' für den Abschluss der Eingabe senden statt nur '\n'.

Re: Shell-Programm mit Python steuern

Verfasst: Freitag 13. März 2015, 12:40
von jerch
@Hansen93:
Gib dem Terminalprogramm mal etwas mehr Zeit zum Starten (wieviel kannst Du selbst rausfinden, wenn Du es selbst am Terminal startest), und lies dann mal den Terminalbuffer aus. Ich vermute, dass da irgendwelche Steuerzeichen drin sind, die dazu führen, dass Dein expect-string nicht matcht.

Re: Shell-Programm mit Python steuern

Verfasst: Freitag 13. März 2015, 13:21
von Hansen93
Super Danke! So langsam komme ich dahinter. MISES wird im Hintergrund ausgeführt und über den Befehl child.interact() kann ich sichtbar machen, dass es zumindest läuft. Das Problem an der Sache ist nur, dass ich jetzt über die Tastatur mit dem Programm interagiere. Gibt es die Möglichkeit den Automatismus, den ich erreichen will, in der Shell sichtbar zu machen? Sprich man sieht hinterher, wie die einzelnen Schritte durchgeführt werden. :wink:

Re: Shell-Programm mit Python steuern

Verfasst: Freitag 13. März 2015, 15:06
von BlackJack
@Hansen93: Das `logfile` auf `sys.stdout` setzen sollte da helfen.

Re: Shell-Programm mit Python steuern

Verfasst: Freitag 13. März 2015, 18:31
von Hansen93
Perfekt! Funktioniert, vielen Dank für die Hilfe!;)