anwendung des subprocess moduls

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
Pablo Escobar
User
Beiträge: 21
Registriert: Montag 12. November 2007, 15:15
Wohnort: Stuttgart

Servus,
vorab ich weiss, es gibt schon zich threads zu dem thema
und ich hab auch einige durchgearbeitet und mir die modul dokumentation durchgelesen
es tut mir auch leid, dass ich hier nochma zum subprocess modul nachfragen muss und weiter auf diesem leidigen thema rumreite

nur irgendwie hängt es bei mir immer noch, wahrscheinlich ist mein verstand einfach zu begrenzt^^
bin in python der absolute anfänger, ein, zwei tutorials durchgearbeitet, hier im forum rumgelesen und mir die library nen bisserl angeguckt

Mein erster Versuch war nun mit hilfe des subprocess moduls die windoof eingabeaufforderung zu öffnen, dort einen befehl zu schreiben und die rückgabe auszulesen.
wie vorrauszusehen hat es nicht funktioniert
nun ist die frage, was sagen mir die fehlermeldungen genau
und wie falsch ist mein quellcode

Code: Alles auswählen

#! /usr/bin/env python
#komtest1.py

# Module importieren:
#-------------------------------------
import subprocess
import os
import sys

# Funktionen:
#--------------------------------------
def befehl(blist): # funktion mit parameter blist zur kommunikation mit einem programm, 
#in blist stehen programm und zuübermittelnde befehle
  subprocess.Popen(blist,bufsize=0,stdin=subprocess.PIPE,stderr=subprocess.PIPE,stdout=subprocess.PIPE)
  subprocess.wait() #warten bis sequenz abgearbeitet ist und bis rückgabewerte geliefert wurden
  print process.stdout.read()
  print process.stderr.read()
in der python shell hab ich dann dies eingegeben:

Code: Alles auswählen

>>> ================================ RESTART ================================
>>> blist = 'cmd, netstat -n'  # soll eine Sequenz abzuarbeitender Befehle werden, 
#cmd soll die Eingabeaufforderung von windoof öffnen,
# --si servers soll dann in diese eingegeben werden
>>> import komtest1 # einbinden der datei die ich geschrieben habe(oberer quellcode)
>>> komtest1.befehl(blist) #aufrufen der funktion die in komtest1 geschrieben wurde mit der variable blist als parameter

Traceback (most recent call last):
  File "<pyshell#11>", line 1, in -toplevel-
    komtest1.befehl(blist)
  File "C:\Python24\komtest1.py", line 12, in befehl
    subprocess.Popen(blist,bufsize=0,stdin=subprocess.PIPE,stderr=subprocess.PIPE,stdout=subprocess.PIPE)
  File "C:\Python24\lib\subprocess.py", line 542, in __init__
    errread, errwrite)
  File "C:\Python24\lib\subprocess.py", line 706, in _execute_child
    startupinfo)
WindowsError: [Errno 2] Das System kann die angegebene Datei nicht finden
>>> 
also blist soll ne sequenz werden die er abarbeiten soll
ich schätze mal dass er mit cmd nichts anfangen kann, da werde ich noch suchen wie dies richtig funktioniert, vielleicht via einem befehl von dem modul os, schaun mer mal
dafür wird wohl der windowserror stehen oder?

was sollen mir die fehler davor sagen?

ansonsten kurzes verständnis zu subprocess:
bei popen die args sind die befehle die ausgeführt werden
stdout = subprocess.PIPE liefert mir dann die rückgabewerte des programmes welches ich ausführe oder?
wird nachdem die befehlssequenz abgearbeitet wurde, die rückgabewerte ausgelesen wurden, das programm was mit hilfe von subprocess geöffnet wurde automatisch geschlossen oder läuft es im hintergrund weiter und ich muss es via extra befehl schließen?

ich bin für jede hilfe, jeden tipp, jeden anreiz dankbar und ihr braucht euch nicht zurückhalten, sprich:
wenn der quellcode das schlechteste ist was ihr je gesehn habt und ich des Programmierens nicht mächtig bin
könnt ihr das gerne sagen, mir hilft momentan so ziemlich alles weiter ^^

also seid bedankt für eure mühen

gruß
Pablo
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Hallo Pablo Escobar

Auf diesem Wege bekommst du bei WindowsXP deine cmd.exe

Code: Alles auswählen

In [2]: import os

In [3]: os.environ["COMSPEC"]
Out[3]: 'C:\\WINDOWS\\system32\\cmd.exe'
Weiß gerade nicht ob das zu älteren Windowsversionen identisch ist.

Zu subprocess kann ich dir leider gerade nicht viel sagen, da ich meinen Projekten meist python23 kompatible bleiben und die alten spawn methoden benutzen muss. Aber ich denke da finden sich genug infos hier oder im web.
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

Schau mal, was du machst:

Code: Alles auswählen

>>> import subprocess
>>> subprocess.Popen('cmd, netstat -n',bufsize=0,stdin=subprocess.PIPE,stderr=subprocess.PIPE,stdout=subprocess.PIPE)

Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    subprocess.Popen('cmd, netstat -n',bufsize=0,stdin=subprocess.PIPE,stderr=subprocess.PIPE,stdout=subprocess.PIPE)
  File "C:\Python25\lib\subprocess.py", line 593, in __init__
    errread, errwrite)
  File "C:\Python25\lib\subprocess.py", line 815, in _execute_child
    startupinfo)
WindowsError: [Error 2] Das System kann die angegebene Datei nicht finden
Diesen Befehl gibt es halt nicht.

Code: Alles auswählen

subprocess.Popen('netstat -n',bufsize=0,stdin=subprocess.PIPE,stderr=subprocess.PIPE,stdout=subprocess.PIPE)
<subprocess.Popen object at 0x00BBE830>
Diesen Befehl gibt es aber sehrwohl! Vielleicht hilft das :3
Pablo Escobar
User
Beiträge: 21
Registriert: Montag 12. November 2007, 15:15
Wohnort: Stuttgart

hm bringt mich noch nicht sehr weiter
ich möchte halt die eingabeaufforderung öffnen
und dort dann Befehle über Python eingeben, die rückgabewerte dann auslesen und mit diesen weiterarbeiten

das ganze soll nen skript werden was die ganze zeit im hintergrund abläuft sobald ich es starte und gewisse sachen kontrolliert

"netstat -n" war jetzt nen beispiel befehl der zufällig auch funktioniert ohne dass ich das command prompt extra öffnen muss
aber wenn ich z.b. "dir /p" als befehl wähle funktioniert das schon wieder nicht

Die Funktion umgangssprachlich formuliert:
öffne die windows eingabeaufforderung
schreibe einen befehl in das eingabeaufforderungsfenster
lese/speichere die reaktion der eingabeaufforderung aus/ab


die frage ist nun
liegt ich auf dem richtigen weg, ist mein quellcode kompletter blödsinn
steh grad relativ aufm schlauch ...

edit:
wenn ich shell = true setze
muss ich die eingabeaufforderung gar nicht extra öffnen?
mit shell=true läuft auch der befehl "dir /p" jetzt beispielsweise
Zuletzt geändert von Pablo Escobar am Mittwoch 28. November 2007, 13:12, insgesamt 1-mal geändert.
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Du bist schon auf dem richtigen Weg.
Teste mal folgendes:

Code: Alles auswählen

test = subprocess.Popen("cmd /c dir", stdout=subprocess.PIPE)
print test.stdout.read()
BlackJack

``dir`` funktioniert nicht, weil das kein Programm sondern ein eingebauter Befehl der Shell (command.com/cmd.exe) ist.

Warum willst Du eigentlich unbedingt die Eingabeaufforderung öffnen und *da* dann andere Programme starten? Das klingt nach einem unnötigen Mittelsmann.
Pablo Escobar
User
Beiträge: 21
Registriert: Montag 12. November 2007, 15:15
Wohnort: Stuttgart

Code: Alles auswählen

>>> test = subprocess.Popen('si servers',bufsize=0,stdin=subprocess.PIPE,stderr=subprocess.PIPE,stdout=subprocess.PIPE, shell=True)
>>> print test.stdout.read()
das funktioniert jetzt :)
danke euch schon mal für eure hilfe

naja wofür ich die eingabeaufforderung brauche:
die eingabeaufforderung ist das command line interface eines programmes
um in diesem programm bestimmte abläufe zu automatisieren brauch ich ein
skript welches in python geschrieben werden soll
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Dafuer gibt es bei Popen den Parameter shell. Wird er auf True gesetzt, wird das Kommando in einer Shell ausgefuehrt, zumindest geht das unter Linux so. Beispiel: Unter linux gibt es den Shell-Befehl 'help', der kein eigenstaendiges Programm ist:

Code: Alles auswählen

>>> subprocess.Popen("help")
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "/usr/lib/python2.4/subprocess.py", line 543, in __init__
    errread, errwrite)
  File "/usr/lib/python2.4/subprocess.py", line 975, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory
Mit shell=True wird das in einer Shell ausgewertet:

Code: Alles auswählen

>>> subprocess.Popen("help", shell=True)
GNU bash, version 3.1.17(1)-release (i486-pc-linux-gnu)
These shell commands are defined internally.  Type `help' to see this list.
Type `help name' to find out more about the function `name'.
Use `info bash' to find out more about the shell in general.
Use `man -k' or `info' to find out more about commands not in this list.

...
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
BlackJack

Das beantwortet alles noch nicht wirklich was die Shell da soll, ich habe eher den Verdacht du denkst zu kompliziert. Warum genau brauchst Du die Shell? Solange Du keine Befehle *von* der Shell benötigst, ist das einfach nur ein unnötiger Prozess der zwischen Deinem Skript und dem Programm sitzt, mit dem Du eigentlich kommunizieren möchtest.
Pablo Escobar
User
Beiträge: 21
Registriert: Montag 12. November 2007, 15:15
Wohnort: Stuttgart

hm
es kann gut sein dass ich von hinten durchs knie in die brust schiesse

allerdings fällt mir keine andere möglichkeit ein als mein programm über das command line interface des progs zu steuern, welches in diesem fall die shell ist.

deswegen geb ich mit python befehle an die shell weiter

wie gesagt wüsste nicht wie ich dem programm ohne übers cli zu gehen, sagen könnte mach dies mach das mach jenes
kann gut sein dass ich grad über paris nach rom fahre
BlackJack

Alles was Du an die Shell gibst, gibt die an das Programm weiter und dessen Ausgaben gehen über die Shell an Dich zurück. Ich glaube diese Diskussion was CLI bedeutet hatten wir schon einmal, ohne Ergebnis, geführt.
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

"Command line interface" eines Programmes bedeutet nichts weiter, als dass dieses Programm drei File-Objekte oeffnet: Einen, von der es Eingabe liest (stdin), einen, um die Ausgabe zu schreiben (stdout) und einen, um Fehlermeldungen rauszuschreiben (stderr). Du kannst dich mit subproccess.Popen direkt an diese Fileobjekte dranhaengen und darueber mit dem Programm kommunizieren. Eine Shell/Cmd ist dazu nicht noetig.

Genau genommen macht die Shell/Cmd beim Ausfuehren eines Programmes nichts anderes, als Tastatureingaben an stdin des Programms zu schicken und den Inhalt von stdout und stderr auf den Bildschirm auszugeben.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Pablo Escobar
User
Beiträge: 21
Registriert: Montag 12. November 2007, 15:15
Wohnort: Stuttgart

naja es kann sein dass die befehle die ich an die shell schicke genauso funktionieren würden wenn ich sie direkt ans programm schicken würd
müsste ich ausprobieren
nur bin ich so schon mal recht zufrieden

ich geh halt immer übers cli weil ich dafür befehlsdokumentationen hab und ich da hundert prozentig weiss das es dann klappt

ich wüsste spontan nicht wie ich nen programm was ich rein über die graphische benutzeroberfläche benutze mit hilfe von python steuern kann weil ich keine ahnung hätte welche befehle beim anklicken bestimmter sachen gesendet werden
BlackJack

Das mit den grafischen Anwendungen ist auch schwierig(er). Aber das stand hier ja gar nicht zur Debatte.

Der Sachverhalt mal an einer Grafik dargestellt. i, o, und e stehen jeweils für die Standardeingabe, -ausgabe, und -fehlerausgabe des Prozesses an dessen Rechteck sie stehen.

Code: Alles auswählen

                       +------------------+       +-------+
         Tastatur ---->|                  |----->i|       |
 1. (a)                |Eingabaufforderung|<-----o|cmd.exe|
          Fenster <----|                  |<-----e|       |
                       +------------------+       +-------+

                       +------------------+       +-------+       +-------+
         Tastatur ---->|                  |----->i|       |----->i|       |
    (b)                |Eingabaufforderung|<-----o|cmd.exe|<-----o|foo.exe|
          Fenster <----|                  |<-----e|       |<-----e|       |
                       +------------------+       +-------+       +-------+

                                   +------+       +-------+       +-------+
                                   |      |----->i|       |----->i|       |
 2.                                |bar.py|<-----o|cmd.exe|<-----o|foo.exe|
                                   |      |<-----e|       |<-----e|       |
                                   +------+       +-------+       +-------+

                                   +------+                       +-------+
                                   |      |--------------------->i|       |
 3.                                |bar.py|<---------------------o|foo.exe|
                                   |      |<---------------------e|       |
                                   +------+                       +-------+
1a) ist das normale Bild was man bekommt, wenn man die Eingabeaufforderung im Menü anklickt. Das ist zum einen ein Windows-Programm, welches das Fenster darstellt und es wird das Konsolenprogramm `cmd.exe` gestartet. `cmd.exe` wartet auf Text auf seinem `stdin`. Wenn man jetzt etwas eintippt, dann nimmt das Windowsprogramm die Tastendrücke entgegen und sendet sie an `cmd.exe` weiter. Wenn man zum Beispiel ``dir`` + Eingabetaste eingibt, dann interpretiert `cmd.exe` das als Befehl, liest die Vezeichnisinformation aus und gibt sie formatiert auf seinem `stdout` aus. Das Fensterprogramm nimmt das entgegen und malt die Buchstaben in das Fenster.

Wenn man etwas eingibt, das `cmd.exe` nicht kennt wird das als Programmname interpretiert und die `cmd.exe` sucht das Programm im `%PATH%` und startet es dann. Und solange das Programm, im Bild 1b) die `foo.exe` läuft, schaltet `cmd.exe` auf "Durchzug". Alles was über die Tastatur eingegeben wird geht an `stdin` der `cmd.exe` und wird direkt weitergeleitet an `stdin` von `foo.exe`. In der umgekehrten Richtung genauso: Alles was `foo.exe` über `stdout` oder `stderr` ausgibt wird von `cmd.exe` an das Fenster zum anzeigen weiter gereicht.

2. Zeigt die Situation wie es aussieht, wenn man von Python aus etwas mit `subprocess` und ``shell=True`` startet. Sobald `foo.exe` läuft, reicht die `cmd.exe` in der Mitte die Kommunikation nur durch und tut sonst selbst nichts.

Das kann man wie in 3., bei ``shell=False`` bzw. weglassen des Arguments, auch einfacher haben.

``shell=True`` braucht man nur, wenn man irgend etwas braucht, was die Shell, in diesem Fall `cmd.exe`, *vor* dem Starten des Programms macht, oder wenn man gar kein Programm starten will, sondern einen eingebauten Befehl der Shell benötigt.
Antworten