subprocess stdin

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
zweig1971
User
Beiträge: 3
Registriert: Donnerstag 1. August 2013, 13:10

Hallo,

ich hab da ein kleinen Problem mit python,
Ich möchte über python ein shell script in linux ausführen.
Das shell script generiert Normale Nachrichten & Fehlermeldungen.

Code: Alles auswählen

#test_script.sh
#!/bin/bash

echo "Hello this is a normal message"
echo "Hello this is an error message, error error" >&2  #stderr kanal

read "Everything good (y/n): " ans

if [ "$ans" == "y" ]; then
        echo "...then everything is okey..."
else
        echo "...this is boring..."
fi
okay das geht ja bekanntlich mit subprocess

Code: Alles auswählen

path = "[...]/test_script.sh"
process = subprocess.Popen([path], stderr=subprocess.PIPE, stdout = subprocess.PIPE, stdin = subprocess.PIPE)
process.wait()

print "normal text :",process.stdout.read()
print "error text  :",process.stderr.read()
aber was mache ich mit der (y/n) Abfrage im shell script ?
Normalerweise würde ich jetzt sagen :
shell script:
read -p "Everything good (y/n): " ans >&0

in python:
process.stdin.read()

aber das funktioniert nicht. Wenn ich unter python data=process.communicate(input='y\n')[0] anwende bleibt das python script hängen...

kann jemand helfen ?


danke & Gruß

zweig1971
Sirius3
User
Beiträge: 17746
Registriert: Sonntag 21. Oktober 2012, 17:20

@zweig1971: Nach stdin schreibt man, "process.stdin.write(...)", und ich hoffe Du benutzt "communicate" statt "wait" und "stdout.read".
Ansonsten solltest Du genau beschreiben, was Du machst.
BlackJack

@zweig1971: Erstmal ist der `wait()`-Aufruf problematisch. Den darfst Du nicht machen solange Du noch erwartest, dass das externe Programm irgendwelche Ausgaben macht, denn dann kann es passieren, dass alles hängen bleibt wenn der oder die Puffer zwischen den beiden Prozessen voll sind. Das externe Programm wartet dann darauf das Dein Programm die Ausgaben abnimmt, damit es weiter schreiben kann, während Dein Programm darauf wartet, dass das externe Programm endlich zum Ende kommt. Was es aber nicht kann solange es seine Ausgaben nicht los wird. Klassische Verklemmung.

Ähnliches gilt für das erste `read()` — da kann es sein, dass eine Verklemmung entsteht weil das erste `read()` auf alle Daten im ersten „Kanal” wartet, während das externe Programm darauf wartet dass Du endlich die Daten auf dem zweiten „Kanal” abnimmst. Und wieder warten beide aufeinander bis zum Sankt Nimmerleinstag.

Wenn ich das Shell-Skript korrigiere — da fehlt ein ``-p`` beim ``read`` — dann funktioniert `communicate()` bei mir.
zweig1971
User
Beiträge: 3
Registriert: Donnerstag 1. August 2013, 13:10

Hallo,

vielen dank für die Tips.
Ich hatte das nicht verstanden mit dem read & communicate. Die read Anweisungen blockierten sich tatsächlich gegenseitig.
Ich hab mir daraufhin die Anweisung communicate noch mal genauer angeschaut und jetzt verstehe ich es (so ungefähr).

mit python code :
print process.communicate('y')

bekommt man :
('Hello this is a normal message\n...then everything is okey...\n', 'Hello this is an error message, error error\n')

wie ich das jetzt verwursten soll ist mir noch nicht so klar, aber das ist ein anderes Problem...

vielen dank !
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Das ist ein ganz normales Tupel, was du da zeigst, das sollte sich genau wie andere Tupel auch verarbeiten lassen. Auch wenn ich es hochgradig seltsam finde dass da bei dir ein Tupel rausfällt.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Sirius3
User
Beiträge: 17746
Registriert: Sonntag 21. Oktober 2012, 17:20

@Leonidas: »communicate« liefert immer ein Tulpe (stdout, stderr) zurück, würde etwas anderes da stehen, fände ich es hochgradig seltsam.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Sirius3 hat geschrieben:@Leonidas: »communicate« liefert immer ein Tulpe (stdout, stderr) zurück, würde etwas anderes da stehen, fände ich es hochgradig seltsam.
War schon spät :oops: Dachte das wäre die Ausgabe von einem Channel der ein in Zeilen gesplittetes Tupel ist.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
zweig1971
User
Beiträge: 3
Registriert: Donnerstag 1. August 2013, 13:10

Hallo,

sehe ich das richtig, das wenn ich communicate benutze, ich die Antwort auf fragen vom script schon vorher wissen muß ?
was mache ich, wenn mir das script unbekannt ist ?

ich hab mir communicate in subprocess.py angeschaut. Es besteht ja im wesentlichen aus drei Teilen :

Code: Alles auswählen

if p.stdin:
 print "I am in stdin"
 p.stdin.write('y')
 p.stdin.close()

if p.stdout:
 print "I am in stdout"
 print p.stdout.read()
 p.stdout.close()

if p.stderr:
 print "I am in stderr"
 print p.stderr.read()
 p.stderr.close()
Ich würde jetzt erst mal Text von p.stdout.read nach einen Fragezeichen suchen und wenn ich eins gefunden habe, den Benutzer eine Eingabe anbieten und diese dann an p.stdin.write weitergeben.

Das geht leider nicht, da scheinbar immer erst stdin abgearbeitet werden muß bevor ich an stdout und stderr drankomme, ist das richtig ?

danke & Gruß

zweig1971
Sirius3
User
Beiträge: 17746
Registriert: Sonntag 21. Oktober 2012, 17:20

@zweig1971: ganz richtig. »communicate« deckt halt nur einen (recht häufigen) Spezialfall ab. Willst Du wirklich mit einem anderen Prozeß Frage-Antwort-Kommunizieren mußt Du Dich selbst darum kümmern, Daten zu lesen und zu schreiben, oder Du nutzt ein Modul wie »pexpect« das Dir einige Probleme umgehen hilft.
Antworten