Daten an Subprocess übergeben bzw. im Subprocess auslesen ?

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.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

gerold hat geschrieben:Da ich davon gehört habe, dass unter Windows das Zielprogramm abgebrochen wird, wenn über sys.stdin des Zielprogramms der String "\x1a" geleitet wird
Das könnte man allerdings ganz einfach umgehen, wenn man vor dem Senden ein string_escape macht!

Komischerweise, bleibt aber mein beschriebenes Problem bestehen, wenn man explizit als letztes ein "\x1a" sendet :)

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Die Diskussion über Vor- und Nachteile der Editoren habe ich in den Thread "Freie und komerzielle Editoren" reinverschoben, da der Thread sich selbstständig gemacht hat :wink:
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
snakeseven
User
Beiträge: 408
Registriert: Freitag 7. Oktober 2005, 14:37
Wohnort: Berlin
Kontaktdaten:

Hi Gerold,
dein Sender-Empfänger Beispiel erzeugt in WingIDE folgende Exceptions:

Code: Alles auswählen

WindowsError: (193, '%1 ist keine zul\xe4ssige Win32-Anwendung')

Rückverfolgung (innerste zuletzt):

Datei "C:\Ablage\Python\PythonScripte\sender.py", Zeile 1, in ?
  #!/usr/bin/env python
Datei "C:\Ablage\Python\PythonScripte\sender.py", Zeile 54, in ?
  main()
Datei "C:\Ablage\Python\PythonScripte\sender.py", Zeile 38, in main
  cwd = os.curdir
Datei "C:\Programme\Python24\Lib\subprocess.py", Zeile 542, in __init__
  errread, errwrite)
Datei "C:\Programme\Python24\Lib\subprocess.py", Zeile 706, in _execute_child
  startupinfo)
Als nächstes werde ich es mal mit Active Python probieren. So als letzter Versuch sozusagen.

Gruss, Seven
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

snakeseven hat geschrieben:Als nächstes werde ich es mal mit Active Python probieren. So als letzter Versuch sozusagen.
Hi Seven!

Blöde Frage, aber stimmt bei dir der Pfad zu Python mit dem im Skript überein? Befindet sich "sender.py" im gleichen Ordner wie "empfaenger.py" und rufst du das Skript von dort aus auf? Funktioniert das Skript beim Aufruf von der Kommandozeile aus? Dieses Skript wurde mit WingIDE geschrieben. Es sollte also ziemlich sicher darin auch aufrufbar sein. :?

Code: Alles auswählen

    # Prozess aufrufen
    proc = subprocess.Popen(
        #Linux: ("/usr/bin/python", "empfaenger.py",),
        (r"C:\Python24\python.exe", "empfaenger.py"),
        stdin = subprocess.PIPE,
        stdout = subprocess.PIPE,
        cwd = os.curdir
    )
lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
maguma :D

hallo,

wenn ich mir recht erinnere müsste das unter windows auch so gehen!

Code: Alles auswählen

# Prozess aufrufen 
    proc = subprocess.Popen( 
        #Linux: ("/usr/bin/python", "empfaenger.py",), 
        (r"/Python24/python.exe", "empfaenger.py"), 
        stdin = subprocess.PIPE, 
        stdout = subprocess.PIPE, 
        cwd = os.curdir 
    ) 
ist nur ein gedanke nichts weiteres.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

maguma :D hat geschrieben:wenn ich mir recht erinnere müsste das unter windows auch so gehen!

Code: Alles auswählen

        (r"/Python24/python.exe", "empfaenger.py"), 
Hi!

Ja das könnte funktionieren, vorausgesetzt Python befindet sich auf dem gleichen Laufwerk wie das auszuführende Programm. Habe jetzt aber keine Lust, zu testen, ob nicht doch zumindest der Laufwerksbuchstabe angegeben werden muss. Das mit den Slash statt dem Backslash funktioniert sicher.

Aber wie ich gerade sehe, sucht Python "subprocess.py" im Ordner "C:\Programme\Python24\Lib". Dann dürfte Python bei Seven auch dort zu finden sein. Zumindest einen Ordner höher.

Code: Alles auswählen

Datei "C:\Programme\Python24\Lib\subprocess.py", Zeile 706, in _execute_child
  startupinfo)
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hi Seven!

Ich habe mein Beispiel verbessert. Jetzt funktioniert es, auch wenn dein Python ganz wo anders versteckt ist.

Code: Alles auswählen

    # Prozess aufrufen
    proc = subprocess.Popen(
        (sys.executable, "empfaenger.py"),
        stdin = subprocess.PIPE,
        stdout = subprocess.PIPE,
        cwd = os.curdir
    )
Man beachte "sys.executable".

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
snakeseven
User
Beiträge: 408
Registriert: Freitag 7. Oktober 2005, 14:37
Wohnort: Berlin
Kontaktdaten:

Ja, VIELEN DANK !!
So funktionierts und so kann ich das jetzt in mein Script einbauen. Wieder ein Festplattenzugriff weniger :) Darf ich fragen, wie du auf "sys.executable" gekommen bist ? Nur so zum Nachlesen, um zu kapieren, was es macht.

Grüße, Seven
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

snakeseven hat geschrieben:Darf ich fragen, wie du auf "sys.executable" gekommen bist ? Nur so zum Nachlesen, um zu kapieren, was es macht.
Zum nachlesen gibts die Dokumentation des sys-Moduls :wink:

In der stdlib findet man doch immer wieder neue Sachen, auch wenn man Python schon lange nutzt, so ist das eben.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

snakeseven hat geschrieben:Darf ich fragen, wie du auf "sys.executable" gekommen bist ? Nur so zum Nachlesen, um zu kapieren, was es macht.
Hi Seven!

Das war reine Intuition. Zuerst dachte ich mir, ich müsse die Registry auslesen um zum Pfad zu Python zu kommen. Dann überlegte ich mir, dass es ja auch genügen würde, wenn ich ein Modul imporiere, das immer im Python-Ordner liegt. Also probierte ich "import os; print os.__file__" aus. Dann hätte ich nur mehr den Pfad kürzen und je nach Betriebssystem "python" oder "python.exe" ran hängen müssen.

Während dieses Denkprozesses dachte ich mir aber, dass es doch sicher noch einen einfacheren Weg geben müsse. So bin ich auf "sys" gekommen. Mit "sys.path" komme ich an die Pfade, die von Python bei der Suche nach Modulen durchgesehen werden. Mit "sys.platform" kriege ich raus, ob das Python-Programm unter Windows oder einem anderen System läuft. Also dachte ich mir, dass "sys" der richtige Platz wäre, auch einen Hinweis auf die Executable von Python zu hinterlegen.

Mal schnell wieder "ipython" gestartet und sys importiert. Dann "sys." eingeben und die Tabulatortaste gedrückt. Schon kommt mir das Wort "executable" entgegen. Ein kurzes "sys.executable" zum Ausprobieren ob das den Pfad zur Python-Exe zurück gibt -- das wars.

Manchmal kommt man über zwanzig Ecken doch noch zum richtigen Ergebnis. :o

Zum schnellen Nachlesen nehme ich meist, wenn ich unter Windows arbeite, die CHM-Hilfe-Datei. Index --> Wort eingeben --> gefunden.

Brauche ich es nicht so ausführlich, oder will ich auch noch schnell etwas testen, starte ich "ipython" (mit Readlinesupport).

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Jep, die CHM-Hilfe-Datei nutzte ich auch sehr oft... Die Referenz als PDF ist auch ok, aber langsamer...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
snakeseven
User
Beiträge: 408
Registriert: Freitag 7. Oktober 2005, 14:37
Wohnort: Berlin
Kontaktdaten:

Hallo,
also im Interpreter funktioniert das mit der Datenübergabe, aber wenn
ich das Script mit Py2exe ausführbar mache, dann bekomme ich nachfolgende Fehlermeldungen. Habe als Kommentar daneben geschrieben, was in den betreffenden Programmzeilen steht.
Ohne ...,stdin=subprocess.PIPE) läuft auch die Py2exe Version, aber
dann habe ich ja keine Datenübergabe. Die Fehler in 'subprocess.pyc'
verstehe ich nicht. Habe mir die .pcy angesehen, aber da stehen nur Hyroglyphen drin und außerdem hat die subprocess.pyc im 'dist' Ordner nur 605 Zeilen. Hat einer ne Idee ??

Gruss, Seven

Code: Alles auswählen

---------------------------------------------------------------------
Traceback (most recent call last):
  File "Modul_Handler.py", line 434, in ?  '		# Lookat() = Hauptfunktion (Loop)
  File "Modul_Handler.py", line 174, in Lookat	# init_proz1() (s.u.)
  File "Modul_Handler.py", line 71, in init_proz1	# gv.pz1 = subprocess.Popen('... Modul_1.exe',stdin = subprocess.PIPE)
  File "subprocess.pyc", line 533, in __init__
  File "subprocess.pyc", line 607, in _get_handles
  File "subprocess.pyc", line 634, in _make_inheritable
WindowsError: [Errno 6] Das Handle ist ungültig
---------------------------------------------------------------------

Code: Alles auswählen

def init_proz1(event=None):
    gv.neustart1 = True
    gv.neust1 = 0
    if gv.pz1.poll() == 0:
        gv.pz1 = subprocess.Popen('... Modul_1.exe',stdin = subprocess.PIPE)
    else:
        kill(gv.pz1.pid)
        gv.pz1 = subprocess.Popen('... Modul_1.exe',stdin = subprocess.PIPE)

def kill(pid):
    handle = win32api.OpenProcess(1, 0, pid)
    return (0 != win32api.TerminateProcess(handle, 0))
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Du hast den anderen Thread http://www.python-forum.de/viewtopic.php?t=4941 verfolgt, oder?

Was hast du überhaupt vor??? Lagerst du Teile deines Programms aus und machst mit py2exe daraus Ausführbare Dateien??? Das ist sicherlich nicht der optimale Weg...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
snakeseven
User
Beiträge: 408
Registriert: Freitag 7. Oktober 2005, 14:37
Wohnort: Berlin
Kontaktdaten:

jens hat geschrieben:Du hast den anderen Thread http://www.python-forum.de/viewtopic.php?t=4941 verfolgt, oder?

Was hast du überhaupt vor??? Lagerst du Teile deines Programms aus und machst mit py2exe daraus Ausführbare Dateien??? Das ist sicherlich nicht der optimale Weg...
@1)Ich sehe in dem zitierten Thread nicht die Antwort auf mein Problem. Sollte cPickle dran schuld sein ?

@2)Ich weiss, dass viele hier die Importmethode favorisieren, ich arbeite aber aus gutem Grund mit parallel laufenden Modulen. Die Module müssen wirklich parallel arbeiten und wenn ein Fehler auftritt, beendet der Modul-Handler nur dieses eine Modul und startet es neu. Tritt der Fehler wiederholt auf, wird es ganz gestopt und der Support benachrichtigt. Die einzelnen Module rufen ihrerseits wieder Subprozesse auf, z.B. Lame ode eine Audiobearbeitungssoftware für aufwendige Effekte. Das ganze ist eine Art Miniserver für Audiobearbeitung / Konvertierung etc.. Läuft unter Zope und bis auf die neuen Fehlermeldungen läuft alles rund, inklusive ErrorLogs und Tages-, Wochen-, und Monatsprotokollen als Excel-Tabellen.

Gruss, Seven
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Versuch mal zusätzlich zum stdin=subprocess.PIPE "stdout=subprocess.PIPE" und "stderr=subprocess.PIPE" mit reinzusetzen. Ich könnte mir vorstellen dass py2exe keine vernünftigen Deskriptoren für stdout und stderr zur Verfügung stellt die dupliziert werden könnten...

Ganz davon abgesehen: die Fehlermeldung bezieht sich auf die Zeile in der Quelldatei von subprocess.pyc, also subprocess.py. Da ist rund um die angegenenen Zeilen folgende Funktionen:

Code: Alles auswählen

def _get_handles(self, stdin, stdout, stderr):
            """Construct and return tupel with IO objects:
            p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite
            """
            if stdin == None and stdout == None and stderr == None:
                return (None, None, None, None, None, None)

            p2cread, p2cwrite = None, None
            c2pread, c2pwrite = None, None
            errread, errwrite = None, None

            if stdin == None:
                p2cread = GetStdHandle(STD_INPUT_HANDLE)
            elif stdin == PIPE:
                p2cread, p2cwrite = CreatePipe(None, 0)
                # Detach and turn into fd
                p2cwrite = p2cwrite.Detach()
                p2cwrite = msvcrt.open_osfhandle(p2cwrite, 0)
            elif type(stdin) == types.IntType:
                p2cread = msvcrt.get_osfhandle(stdin)
            else:
                # Assuming file-like object
                p2cread = msvcrt.get_osfhandle(stdin.fileno())
            p2cread = self._make_inheritable(p2cread)

            if stdout == None:
                c2pwrite = GetStdHandle(STD_OUTPUT_HANDLE)
            elif stdout == PIPE:
                c2pread, c2pwrite = CreatePipe(None, 0)
                # Detach and turn into fd
                c2pread = c2pread.Detach()
                c2pread = msvcrt.open_osfhandle(c2pread, 0)
            elif type(stdout) == types.IntType:
                c2pwrite = msvcrt.get_osfhandle(stdout)
            else:
                # Assuming file-like object
                c2pwrite = msvcrt.get_osfhandle(stdout.fileno())
            c2pwrite = self._make_inheritable(c2pwrite) # Fehler hier, 607.

            if stderr == None:
                errwrite = GetStdHandle(STD_ERROR_HANDLE)
            elif stderr == PIPE:
                errread, errwrite = CreatePipe(None, 0)
                # Detach and turn into fd
                errread = errread.Detach()
                errread = msvcrt.open_osfhandle(errread, 0)
            elif stderr == STDOUT:
                errwrite = c2pwrite
            elif type(stderr) == types.IntType:
                errwrite = msvcrt.get_osfhandle(stderr)
            else:
                # Assuming file-like object
                errwrite = msvcrt.get_osfhandle(stderr.fileno())
            errwrite = self._make_inheritable(errwrite)

            return (p2cread, p2cwrite,
                    c2pread, c2pwrite,
                    errread, errwrite)

        def _make_inheritable(self, handle):
            """Return a duplicate of handle, which is inheritable"""
            return DuplicateHandle(GetCurrentProcess(), handle,
                                   GetCurrentProcess(), 0, 1,
                                   DUPLICATE_SAME_ACCESS) # Fehler hier, 634.
Schaut also ganz danach aus dass das handle von stdout nicht dupliziert werden kann. Dagegen kannst Du aber wie gesagt durch obiges was tun.

--- Heiko.
snakeseven
User
Beiträge: 408
Registriert: Freitag 7. Oktober 2005, 14:37
Wohnort: Berlin
Kontaktdaten:

modelnine hat geschrieben:Versuch mal zusätzlich zum stdin=subprocess.PIPE "stdout=subprocess.PIPE" und "stderr=subprocess.PIPE" mit reinzusetzen. Ich könnte mir vorstellen dass py2exe keine vernünftigen Deskriptoren für stdout und stderr zur Verfügung stellt die dupliziert werden könnten... --- Heiko.
Das wars ! Voll in Schwarze getroffen modelnine, keine Fehlermeldungen mehr, danke ! Seven
Antworten