subprocess

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
INFACT
User
Beiträge: 385
Registriert: Freitag 5. Dezember 2008, 16:08

Hi,

Ich versuche gerade einen cmd ersatz für windows zu programmieren.
Das Fenster und so gibt es alles schon, jetzt muss ich aber die Befehle "popen".
Das ist mein Code, den ich bis jetzt geschrieben habe:

Code: Alles auswählen

    def executeInput(self, input):
        sp = subprocess.Popen(input,
                              stdout=subprocess.PIPE,
                              stderr=subprocess.PIPE)
        print ":", sp.stdout.read()
Da habe ich jetzt aber 2 probleme:
1. subprocess führt keine Befehle wie cls oder echo aus. Mit IF habe ich das noch nicht probiert.
2. Was ist denn wenn jetzt ein programm einen input in stdin will? Dann wird mein programm gedost :lol:

Habt ihr irgenteine Idee wie man das verhindern kann?

Edit:

Code: Alles auswählen

 statt [code] verwendet
[b][i]ein kleines game für die die lust haben http://konaminut.mybrute.com[/i][/b]
;-)
BlackJack

@INFACT: Wenn Du einen `cmd.exe`-Ersatz schreiben willst, dann musst Du natürlich auch die eingebauten Befehle und die Programmflusskontrolle mit bedingter Ausführung, Schleifen und so weiter auch selber implementieren. Ebenso die Umleitung von und in Dateien.

Ausserdem musst Du dafür Sorge tragen, dass bei Programmen die auf `stderr` *und* `stdout` Ausgaben tätigen, Dein `cmd.exe`-Ersatz nicht blockiert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

INFACT hat geschrieben: Das Fenster und so gibt es alles schon,
Was genau meinst Du damit?
1. subprocess führt keine Befehle wie cls oder echo aus. Mit IF habe ich das noch nicht probiert.
Woran erkennst Du denn, dass der Befehl nicht ausgeführt wird?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
INFACT
User
Beiträge: 385
Registriert: Freitag 5. Dezember 2008, 16:08

Na toll,

ich wollte eigentlich nur eine coole shell wie bei ubuntu xtce4-terminal .
Wo man verschiedene Farben(für dieses root@rootpc$, stdout, stderr) und Hintergrund (Bilder, Transparenz) optionen und so hat.

Ich hab gedacht das währe leichter, weil ich das mit den Farben und Transparenz mit PyQt schon mal gemacht habe. Ich habe aber nicht gedacht, dass das so schwer währe die eingaben vernünftig zu programmieren.

Kennt jemand sowas vielleicht oder muss ich das doch programmieren? :mrgreen:
[b][i]ein kleines game für die die lust haben http://konaminut.mybrute.com[/i][/b]
;-)
INFACT
User
Beiträge: 385
Registriert: Freitag 5. Dezember 2008, 16:08

Hyperion hat geschrieben:
INFACT hat geschrieben: Das Fenster und so gibt es alles schon,
Was genau meinst Du damit?
Das ich das schon in PyQt4 programmiert habe, also das Gui gibt es schon, nur die Funktionen fehlen
Hyperion hat geschrieben:
1. subprocess führt keine Befehle wie cls oder echo aus. Mit IF habe ich das noch nicht probiert.
Woran erkennst Du denn, dass der Befehl nicht ausgeführt wird?

Code: Alles auswählen

>>> subprocess.call("echo Hi")
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    subprocess.call("echo Hi")
  File "E:\Python26\Lib\subprocess.py", line 444, in call
    return Popen(*popenargs, **kwargs).wait()
  File "E:\Python26\Lib\subprocess.py", line 595, in __init__
    errread, errwrite)
  File "E:\Python26\Lib\subprocess.py", line 821, in _execute_child
    startupinfo)
WindowsError: [Error 2] The system cannot find the file specified
[b][i]ein kleines game für die die lust haben http://konaminut.mybrute.com[/i][/b]
;-)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Naja, wie BlackJack schon schrieb: Du musst halt gucken, welche Kommandos Du an das OS weiterreichen kannst und welche Du selber ausführen musst. Dazu kommt dann noch die entsprechende Ein- / Ausgabeumleitung.

Prinzipiell durchaus eine nette Idee, die durchaus viel Spaß machen kann. Man muss ja auch nicht gleich alles können. Speziell Verschachtelungen oder Schleifen kann man ja auch erst einmal weglassen; diese spielen ja eher bei Scripten eine Rolle - und die kann ich ja auch in der echten DOS-Shell ablaufen lassen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
INFACT
User
Beiträge: 385
Registriert: Freitag 5. Dezember 2008, 16:08

Hab schonmal gefunden wie ich mit subprocess alle befehle ausführen kann:

Code: Alles auswählen

subprocess.Popen('cmd /c "example.bat"')
führt dann diese batch aus:

Code: Alles auswählen

@echo off
echo Hi
pause > nul
Ich kann so auch direkt pause > nul aufrufen.

Für Linuxe: pause > nul heißt einfach das der "Eine beliebige Taste drücken schreibt. und man dann ANY KEY drücken muss.
> nul ist wie > /dev/null

Jetzt muss ich nur noch rausfinden wie ich mit subprocess herausfinden kann ob das programm auf eine Eingabe wartet und die dann ausführt.
[b][i]ein kleines game für die die lust haben http://konaminut.mybrute.com[/i][/b]
;-)
BlackJack

@INFACT: Wenn Du die Eingaben mit `cmd.exe` ausführst um `cmd.exe` zu ersetzen, dann scheint mir das ziemlich Sinnlos!?

Kann es sein dass Du eigentlich gar keine Shell sondern ein Terminal implementieren möchtest? Dann musst Du überhaupt keine Befehle selber implementieren, sondern einfach nur eine grafische Umgebung für die `cmd.exe` schaffen. Also diese einmal starten und die Ein- und Ausgaben mit Deinem Code verbinden. Eventuell musst Du ein Pseudoterminal emulieren damit diese Kanäle nicht gepuffert werden. Ist jedenfalls unter Linux der Fall.
INFACT
User
Beiträge: 385
Registriert: Freitag 5. Dezember 2008, 16:08

BlackJack hat geschrieben:@INFACT: Wenn Du die Eingaben mit `cmd.exe` ausführst um `cmd.exe` zu ersetzen, dann scheint mir das ziemlich Sinnlos!?

Kann es sein dass Du eigentlich gar keine Shell sondern ein Terminal implementieren möchtest? Dann musst Du überhaupt keine Befehle selber implementieren, sondern einfach nur eine grafische Umgebung für die `cmd.exe` schaffen. Also diese einmal starten und die Ein- und Ausgaben mit Deinem Code verbinden. Eventuell musst Du ein Pseudoterminal emulieren damit diese Kanäle nicht gepuffert werden. Ist jedenfalls unter Linux der Fall.
Oh, ä,

Ja das meinte ich :roll: :roll: :roll:

Mist.
Ich versuche gerade stdin richtig hinzubekommen.

Code: Alles auswählen

>>> p = Popen("cmd w", stdout=subprocess.PIPE,
	  stderr=subprocess.PIPE)
>>> p.stdout.read() # das was am anfang im cmd steht
'Microsoft Windows [Version 6.1.7600]\r\nCopyright (c) 2009 Microsoft Corporation.  All rights reserved.\r\n\r\nE:\\Python26>'
>>> p.communicate("echo test") # sollte dann echo test ins cmd eingeben
('', '')
>>> p.stdout.read() # hier sollte dann test stehen 1.)
''
>>> p.stdout.read()
''
Bei 1.) Sollte test stehen, weil man ja echo test ins cmd eingegeben hat.
Wieso klappt das nicht!?

EDIT: bei stderr ist auch nichts zu finden
[b][i]ein kleines game für die die lust haben http://konaminut.mybrute.com[/i][/b]
;-)
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Du solltest die Dokumentation zu subprocess lesen, unbedingt!
Speziell den Abschnitt stdout.read(), stderr.read(), stdin.write() und popen.communicate()

Anbei noch ein Link, der dir vllt. auf die Sprünge helfen kann: http://blog.dav1d.de/code/subprocess-un ... us-stdout/
the more they change the more they stay the same
INFACT
User
Beiträge: 385
Registriert: Freitag 5. Dezember 2008, 16:08

Ja da ist ein problem.

Wenn ich stdin mit pipe mache, dann bekomme ich kein richtiges realtimeoutput.

Code: Alles auswählen

>>> from subprocess import Popen, PIPE
>>> p = Popen("cmd w",
	  stdout=PIPE,
	  stderr=PIPE,
	  stdin=PIPE)
>>> while True:
    line = p.stdout.readline()
    if not line:
        break
    print 'STDOUT>>> ' + repr(line)#.rstrip()

    
STDOUT>>> 'Microsoft Windows [Version 6.1.7600]\r\n'
STDOUT>>> 'Copyright (c) 2009 Microsoft Corporation.  All rights reserved.\r\n'
STDOUT>>> '\r\n'
Aber das hört nicht auf, also break wird nie ausgeführt.


Und wenn ich stdin nicht als parameter angebe, cann ich auch stdin.write nicht ausführen.
[b][i]ein kleines game für die die lust haben http://konaminut.mybrute.com[/i][/b]
;-)
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Du beendest auch den cmd.exe Prozess nie (das geht z.B. mit exit)
the more they change the more they stay the same
INFACT
User
Beiträge: 385
Registriert: Freitag 5. Dezember 2008, 16:08

Wenn ich vorher stdin.write("exit\r\n"), dann wird das beendet.

Dann muss ich aber doch das lesen und schreiben in 2 threads ausführen, oder?
Wenn mir read erst etwas ausgibt, wenn da was neues steht.

Hier mal ein nicht funktionierendes beispiel:

Code: Alles auswählen

>>> from subprocess import Popen, PIPE
>>> p = Popen("cmd w",
          stdout=PIPE,
          stderr=PIPE,
          stdin=PIPE)
>>> def readThread():
	while True:
	    line = p.stdout.readline()
	    if not line:
		break
	    print 'STDOUT>>> ' + repr(line)#.rstrip()

	    
>>> import thread
>>> thread.start_new_thread(readThread, tuple())
5956STDOUT>>> 'Microsoft Windows [Version 6.1.7600]\r\n'

STDOUT>>> 'Copyright (c) 2009 Microsoft Corporation.  All rights reserved.\r\n'
>>> 
STDOUT>>> '\r\n'
p.stdout.write("echo test\r\n")
dir()
pass
exit()
# hier passiert irgentwie nichts
[b][i]ein kleines game für die die lust haben http://konaminut.mybrute.com[/i][/b]
;-)
ichisich
User
Beiträge: 134
Registriert: Freitag 1. Januar 2010, 11:52

Hi,

ohne jetzt dein Problem ganz genau durchgegangen zu sein...
Ich hab neulich Bekanntschaft mit QProcess gemacht und mich um etliches leichter getan als mit subprocess.
Da du ja schon mit PyQt schaffst wäre das auf alle Fälle nen Blick wert.
(Evt ist es aber einfach nur geschmacksache und mir liegt die Doku von Qt besser und sämtliche Funktionen in QProcess und subprocess sind redundant)

Gruß
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Wieso probierst du in der IDLE, das gibt nur ärger?
Mache die auserdem mal mit Queue.Queue vertraut
the more they change the more they stay the same
Antworten