Datenübergabe an STDIN eines neuen Prozesses

Code-Stücke können hier veröffentlicht werden.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hi!

Weil die Frage aufgetaucht ist, wie man über STDOUT und STDIN Daten von einem Prozess zum anderen schicken kann...

Hier eine mögliche Lösung, die mit **cPickle** arbeitet.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
"""
sender.py

Demonstriert die Datenübergaben eines gepickelten Dictionaries an STDIN
eines anderen Prozesses.
"""

import cPickle
import subprocess
import os
import os.path
import sys


#----------------------------------------------------------------------
def main():
    """
    Stellt ein Dictionary zusammen, das zuerst in einen String
    gepickelt und dann an den STDIN des aufgerufenen Programmes
    übergeben wird.
    """
   
    # Dictionary zusammenstellen
    mydict = {
        "vorname": "Gerold",
        "nachname": "Penz",
        "ort": "Oberhofen im Inntal",
    }
   
    # Dictionary in einen String pickeln
    datastring = cPickle.dumps(mydict, 2)
   
    # Prozess aufrufen
    proc = subprocess.Popen(
        (sys.executable, "empfaenger.py"),
        stdin = subprocess.PIPE,
        stdout = subprocess.PIPE,
        cwd = os.curdir
    )
   
    # In den STDIN des neuen Prozesses wird der Datenstring geschrieben
    proc.stdin.write(datastring)
    # STDIN des neuen Prozesses schließen, damit dieser weiter machen kann.
    proc.stdin.close()
   
    # STDOUT des neuen Prozesses auslesen und anzeigen
    print "Vom Sender empfangen und geschrieben:"
    print proc.stdout.read()
    # STDOUT des neuen Prozesses schließen
    proc.stdout.close()
   
   
#----------------------------------------------------------------------
if __name__ == "__main__":
    main() 

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
"""
empfaenger.py

Demonstriert die Datenübernahme eines gepickelten Dictionaries von STDIN.
"""

import cPickle
import sys


#----------------------------------------------------------------------
def main():
    datastring = sys.stdin.read()
    mydict = cPickle.loads(datastring)
    print mydict

    
#----------------------------------------------------------------------
if __name__ == "__main__":
    main()
mfg
Gerold
:-)

EDIT: WARNUNG!!! Dieses Beispiel funktioniert nicht im IDLE.
Endlich mal ein funktionierendes Beispiel eines Programms, das nicht unter Idle läuft. 8)
Getestet unter Windows mit Idle 1.1.1.

EDIT2: Statt dem hart gecodeten Pfad zu Python wird jetzt "sys.executable" verwendet. Damit dürfte es unter Linux und Windows, auch bei verschiedenen Python-Installationen, funktionieren.
Zuletzt geändert von gerold am Freitag 20. Januar 2006, 17:14, insgesamt 4-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Das geht sogar noch ein bissel anders:

sender.py

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
"""
sender.py

Demonstriert die Datenübergaben eines gepickelten Dictionaries an STDIN
eines anderen Prozesses.
"""

import cPickle
import subprocess
import os


#----------------------------------------------------------------------
def main():
    """
    Stellt ein Dictionary zusammen, das zuerst in einen String
    gepickelt und dann an den STDIN des aufgerufenen Programmes
    übergeben wird.
    """
   
    # Dictionary zusammenstellen
    mydict = {
        "vorname": "Gerold",
        "nachname": "Penz",
        "ort": "Oberhofen im Inntal",
    }
   
    # Prozess aufrufen
    proc = subprocess.Popen(
        ("/usr/bin/python", "empfaenger.py",),
        stdin = subprocess.PIPE,
        stdout = subprocess.PIPE,
        cwd = os.curdir
    )
   
    # In den STDIN des neuen Prozesses wird der Datenstring geschrieben
    cPickle.dump(mydict,proc.stdin)
    tmpdict = cPickle.load(proc.stdout)
    print "Unser dict:", mydict
    print "Vom Kind zurückbekommen:", tmpdict

    cPickle.dump("hallo, wie gehts?",proc.stdin)
    tmpstr = cPickle.load(proc.stdout)
    print "Vom Kind gesagt:", tmpstr

    # Weitere Daten einzeln an den Kind-Prozess schicken und auf
    # Antwort warten.
    # ...

    # Wir sind fertig mit dem Daten schicken, Kind-Prozess signalisieren.
    # Wenn wir eine fixe Menge an Daten übertragen brauchen wir das dem
    # Kindprozess nicht zu signalisieren, wir müssen dann nur am Ende
    # stdin auf jeden Fall zumachen.
    proc.stdin.close()

    # STDOUT des neuen Prozesses schließen
    proc.stdout.close()
   
   
#----------------------------------------------------------------------
if __name__ == "__main__":
    main()
empfaenger.py

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
"""
empfaenger.py

Demonstriert die Datenübernahme eines gepickelten Dictionaries von STDIN.
"""

import cPickle
import sys


#----------------------------------------------------------------------
def main():
    while True:
        try:
            mydata = cPickle.load(sys.stdin)
        except:
            # Es konnten keine Daten mehr gelesen werden weil der Parent
            # zugemacht hat. Müßte ein EOFError sein, der hier kommt, weiß
            # ich aber nicht genau, deswegen das generelle except, was nicht
            # ganz in Ordnung ist...
            break
        cPickle.dump(mydata,sys.stdout)
    # Der Parent hat zugemacht. Finalisieren.

   
#----------------------------------------------------------------------
if __name__ == "__main__":
    main()
Die Idee hinter dem ganzen ist dass dump() und load() des (c)Pickle-Moduls nur soweit lesen wie es sich aus dem Dump ergibt, also nicht blockieren wenn der Pickle in Ordnung ist (wovon wir ja mal ausgehen). Ich kann also einen Pickle über die Leitung schieben, und dann den Pickle ohne dass ich die Verbindung zumachen muss wieder über die entgegengesetzte Funktion lesen.

Das eignet sich zum Beispiel auch zur Bidirektionalen Kommunikation, da auch der Client auf stdout etwas per Pickle an den Server zurückschicken kann, so dass dann immer weiter kommuniziert werden kann. Netter Nebeneffekt: wenn keine Daten vorhanden sind blockiert load(), so dass der jeweilige Prozess auf den anderen warten kann indem er einfach load(<pipe>) aufruft.

Erst wenn die Bidirektionale Verbindung nicht mehr gebraucht ist sollte das per schließen von stdin signalisiert werden, und dann im jeweils anderen Prozess dazu führen dass halt die Verbindung abgebaut wird.

Ich sag dazu dass der obige code untested ist; er sollte aber auf jeden Fall so gehen wir da dargestellt.

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

modelnine hat geschrieben:Das geht sogar noch ein bissel anders:
Hi Heiko!

Ich habe es nicht geschafft, dein Beispiel zum Laufen zu bekommen. Hast du es schon einmal ausprobiert?

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Das obige hab ich wie gesagt nicht getestet, aber ich hab was sehr ähnliches als pseudo-IPC benutzt... Ich setz mich gleich noch mal ran, mal gucken, und poste dann das was tut.

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

modelnine hat geschrieben:Das obige hab ich wie gesagt nicht getestet, aber ich hab was sehr ähnliches als pseudo-IPC benutzt...
Hi Heiko!

Ich habe es jetzt auch schon mit `proc.stdin.flush()` probiert, aber es funktioniert nicht unter Windows. Der Code wird bei

Code: Alles auswählen

tmpdict = cPickle.load(proc.stdout)
blockiert. Was muss ich ändern, dass es funktioniert? Was muss gesendet werden, damit der Empfänger weiß, dass er ab jetzt arbeiten soll? Was braucht es, dass der Sender weiß, dass er ab jetzt die vom Empfänger empfangenen Daten auswerten soll?

Wenn dein Beispiel zum Laufen überredet werden kann, dann wäre das wirklich eine einfach einzusetzende bidirektionale Kommunikation zwischen einzelnen Prozessen. Man bräuchte keine eigenständig laufenden Serverprogramme, man muss keine Ports bei der lokalen Firewall frei schalten, usw.

lg
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 Heiko!

Wenn ich wieder ein wenig Zeit habe, dann probiere ich es auf eine andere Art aus. Vielleicht ist der Empfänger dazu zu bewegen, immer nur ein Byte zu lesen. Dann sammle ich die einzelnen Bytes bis ein Abbruchsignal übermittelt wird. Dann schiebe ich den gesammelten Bytestring in ein Pickle-Objekt, arbeite damit, gebe wieder Daten zurück und fange wieder mit Bytesammeln an.

Das probiere ich in ein paar Tagen aus. Vielleicht geht es ja auf diese Art.

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:

Ist es nicht evtl. das selbe Problem was ich hier http://www.python-forum.de/viewtopic.php?p=29568#29568 geschildert hab???

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Humm... Es kann sein dass es unter Windows Probleme damit gibt weil stdin gebuffered ist. Unter Unix hab ich keinerlei Probleme damit. Kleines Beispiel:

Folgende Ausgabe wird produziert:

Code: Alles auswählen

modelnine@phoenix ~ $ python test2.py
Subprocess started!
Writing data to subprocess: ['test', '123', 1234]
Received in subprocess: ['test', '123', 1234]
Got data from subprocess: ['test', '123', 1234]
Writing data to subprocess: ['test', '123', 1234]
Received in subprocess: ['test', '123', 1234]
Got data from subprocess: ['test', '123', 1234]
Writing data to subprocess: ['test', '123', 1234]
Received in subprocess: ['test', '123', 1234]
Got data from subprocess: ['test', '123', 1234]
Writing data to subprocess: ['test', '123', 1234]
Received in subprocess: ['test', '123', 1234]
Got data from subprocess: ['test', '123', 1234]
Writing data to subprocess: ['test', '123', 1234]
Received in subprocess: ['test', '123', 1234]
Got data from subprocess: ['test', '123', 1234]
Writing data to subprocess: ['test', '123', 1234]
Received in subprocess: ['test', '123', 1234]
Got data from subprocess: ['test', '123', 1234]
Writing data to subprocess: ['test', '123', 1234]
Received in subprocess: ['test', '123', 1234]
Got data from subprocess: ['test', '123', 1234]
Writing data to subprocess: ['test', '123', 1234]
Received in subprocess: ['test', '123', 1234]
Got data from subprocess: ['test', '123', 1234]
Writing data to subprocess: ['test', '123', 1234]
Received in subprocess: ['test', '123', 1234]
Got data from subprocess: ['test', '123', 1234]
Writing data to subprocess: ['test', '123', 1234]
Received in subprocess: ['test', '123', 1234]
Got data from subprocess: ['test', '123', 1234]
Closed stdin and out for subprocess. Terminating.
modelnine@phoenix ~ $ Parent has closed connection. Terminating.
von folgenden Skripten:

test1.py

Code: Alles auswählen

import pickle
import sys

# Daten lesen und gleich wieder dumpen.
sys.stderr.write("Subprocess started!\n")
while True:
    try:
        data = pickle.load(sys.stdin)
        sys.stderr.write("Received in subprocess: %r\n" % data)
    except EOFError:
        sys.stderr.write("Parent has closed connection. Terminating.\n")
        break
    pickle.dump(data,sys.stdout)
    sys.stdout.flush()
test2.py

Code: Alles auswählen

import pickle
import subprocess

proc = subprocess.Popen(["python","test1.py"],0,None,
                        subprocess.PIPE,subprocess.PIPE,None)

data = ["test","123",1234]
for i in range(10):
    print "Writing data to subprocess:", data
    pickle.dump(data,proc.stdin)
    newdata = pickle.load(proc.stdout)
    print "Got data from subprocess:", newdata

proc.stdin.close()
proc.stdout.close()

print "Closed stdin and out for subprocess. Terminating."
Probier das mal auf einer Windows-Kiste aus...

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

modelnine hat geschrieben:Probier das mal auf einer Windows-Kiste aus...
Hi Heiko!

Ich sehe die Meldung, kann sie aber nicht deuten. :oops:

Code: Alles auswählen

C:\Dokumente und Einstellungen\Gerold\Desktop\Neuer Ordner>test2.py
Writing data to subprocess: ['test', '123', 1234]
Subprocess started!
Received in subprocess: ['test', '123', 1234]
Traceback (most recent call last):
  File "C:\Dokumente und Einstellungen\Gerold\Desktop\Neuer Ordner\test2.py", line 11, in ?
    newdata = pickle.load(proc.stdout)
  File "C:\Python24\lib\pickle.py", line 1390, in load
    return Unpickler(file).load()
  File "C:\Python24\lib\pickle.py", line 872, in load
    dispatch[key](self)
  File "C:\Python24\lib\pickle.py", line 980, in load_string
    raise ValueError, "insecure string pickle"
ValueError: insecure string pickle
Parent has closed connection. Terminating.

C:\Dokumente und Einstellungen\Gerold\Desktop\Neuer Ordner>
Ich sehe mir das später mal an, wenn ich mehr Zeit übrig habe.

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:

gerold hat geschrieben:Ich sehe die Meldung, kann sie aber nicht deuten. :oops:

Code: Alles auswählen

ValueError: insecure string pickle
naja, das sieht so aus, also ob die übergebenen Daten nicht mehr richtig sind...
Vielleicht einfach nur ein Fehler mit den unterschiedlichen Zeilenendenzeichen?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Humm... Das ist ein ganz seltsamer Fehler, der eingentlich nur auftritt wenn der Pickle kaputt ist (der code der das prüft guckt ob der gepickelte String mit einem " oder ' anfängt, und wenn ja, dass er auch mit dem selben Zeichen aufhört, und wenn er eine Bedingung nicht erfüllt wird der Fehler geschmissen). Liegt wahrscheinlich an universal_newlines=False (da das letzte Zeichen bei Dir mit großer Wahrscheinlichkeit ein \r ist, wegen der besch... Windows-Konvention von \r\n, und readline() was da benutzt wird nur \n wegschmeißt als Separator).

Probier mal beim Konstruieren des subprocess-Objekts ein universal_newlines=True zu setzen, und schau dann ob es geht. Sonst: Du kannst natürlich auch probieren einen binären Pickle über die Leitung zu schieben; das sollte eigentlich auch gehen, unabhängig von universal_newlines.

Dazu gibst Du dem pickle.dump-Aufruf protocol=pickle.HIGHEST_PROTOCOL mit.

--- Heiko.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ich hab es mal jetzt getestet und es kommt genau zu dem Fehler den gerold geschrieben hat... Mit universal_newlines=True hab ich es auch Probiert, bringt aber anscheinend auch nicht viel...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Im Endeffekt liegts daran dass stdin mit mode "w" geöffnet wird. Bedeutet also dass die bescheuerte Interpretierung von Zeilenenden \n -> \r\n von Windows gemacht wird. Man kann aber bei subprocess nicht einstellen dass die Pipe binary sein soll, was irgendwie extrem nervt.

Mal schauen. Ich weiß warum ich Windows nicht mag. Jeden Tag wieder.

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

Lala... Folgendes sollte tun:

test1.py

Code: Alles auswählen

import pickle
import sys

# Daten lesen und gleich wieder dumpen.
sys.stderr.write("Subprocess started!\n")
while True:
    try:
        data = pickle.load(sys.stdin)
        sys.stderr.write("Received in subprocess: %r\n" % data)
    except EOFError:
        sys.stderr.write("Parent has closed connection. Terminating.\n")
        break
    pickle.dump(data,sys.stdout)
    sys.stdout.flush()
test2.py

Code: Alles auswählen

import pickle
import subprocess

proc = subprocess.Popen(["python","-u","test1.py"],0,None,
                        subprocess.PIPE,subprocess.PIPE,None)

data = ["test","123",1234]
for i in range(10):
    print "Writing data to subprocess:", data
    pickle.dump(data,proc.stdin)
    newdata = pickle.load(proc.stdout)
    print "Got data from subprocess:", newdata

proc.stdin.close()
proc.stdout.close()

print "Closed stdin and out for subprocess. Terminating."
--- Heiko.
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Informationen dazu gibts unter:

http://www.python.org/doc/faq/windows.h ... t-or-win95

--- Heiko.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ach doch... jetzt scheint es zu gehen... Hab mal aus newdata nur data gemacht und einen counter eingebaut... Zumindest in der Konsole geht's richtig:
Writing data to subprocess: ['Counter1:', 0, 'Counter2:', 1]
Subprocess started!
Received in subprocess: ['Counter1:', 0, 'Counter2:', 1]
Got data from subprocess: ['Counter1:', 1, 'Counter2:', 1]
Writing data to subprocess: ['Counter1:', 1, 'Counter2:', 2]
Received in subprocess: ['Counter1:', 1, 'Counter2:', 2]
Got data from subprocess: ['Counter1:', 2, 'Counter2:', 2]
Writing data to subprocess: ['Counter1:', 2, 'Counter2:', 3]
Received in subprocess: ['Counter1:', 2, 'Counter2:', 3]
Got data from subprocess: ['Counter1:', 3, 'Counter2:', 3]
Writing data to subprocess: ['Counter1:', 3, 'Counter2:', 4]
Received in subprocess: ['Counter1:', 3, 'Counter2:', 4]
Got data from subprocess: ['Counter1:', 4, 'Counter2:', 4]
Writing data to subprocess: ['Counter1:', 4, 'Counter2:', 5]
Received in subprocess: ['Counter1:', 4, 'Counter2:', 5]
Got data from subprocess: ['Counter1:', 5, 'Counter2:', 5]
Writing data to subprocess: ['Counter1:', 5, 'Counter2:', 6]
Received in subprocess: ['Counter1:', 5, 'Counter2:', 6]
Got data from subprocess: ['Counter1:', 6, 'Counter2:', 6]
Writing data to subprocess: ['Counter1:', 6, 'Counter2:', 7]
Received in subprocess: ['Counter1:', 6, 'Counter2:', 7]
Got data from subprocess: ['Counter1:', 7, 'Counter2:', 7]
Writing data to subprocess: ['Counter1:', 7, 'Counter2:', 8]
Received in subprocess: ['Counter1:', 7, 'Counter2:', 8]
Got data from subprocess: ['Counter1:', 8, 'Counter2:', 8]
Writing data to subprocess: ['Counter1:', 8, 'Counter2:', 9]
Received in subprocess: ['Counter1:', 8, 'Counter2:', 9]
Got data from subprocess: ['Counter1:', 9, 'Counter2:', 9]
Writing data to subprocess: ['Counter1:', 9, 'Counter2:', 10]
Received in subprocess: ['Counter1:', 9, 'Counter2:', 10]
Got data from subprocess: ['Counter1:', 10, 'Counter2:', 10]
Parent has closed connection. Terminating.
Closed stdin and out for subprocess. Terminating.
In SciTE kommt reproduzierbar dieses:
Writing data to subprocess: ['Counter1:', 0, 'Counter2:', 1]
Got data from subprocess: ['Counter1:', 0, 'Counter2:', 1]
Writing data to subprocess: ['Counter1:', 0, 'Counter2:', 2]
Got data from subprocess: ['Counter1:', 0, 'Counter2:', 2]
Writing data to subprocess: ['Counter1:', 0, 'Counter2:', 3]
Got data from subprocess: ['Counter1:', 0, 'Counter2:', 3]
Writing data to subprocess: ['Counter1:', 0, 'Counter2:', 4]
Got data from subprocess: ['Counter1:', 0, 'Counter2:', 4]
Writing data to subprocess: ['Counter1:', 0, 'Counter2:', 5]
Got data from subprocess: ['Counter1:', 0, 'Counter2:', 5]
Writing data to subprocess: ['Counter1:', 0, 'Counter2:', 6]
Got data from subprocess: ['Counter1:', 0, 'Counter2:', 6]
Writing data to subprocess: ['Counter1:', 0, 'Counter2:', 7]
Got data from subprocess: ['Counter1:', 0, 'Counter2:', 7]
Writing data to subprocess: ['Counter1:', 0, 'Counter2:', 8]
Got data from subprocess: ['Counter1:', 0, 'Counter2:', 8]
Writing data to subprocess: ['Counter1:', 0, 'Counter2:', 9]
Got data from subprocess: ['Counter1:', 0, 'Counter2:', 9]
Writing data to subprocess: ['Counter1:', 0, 'Counter2:', 10]
Got data from subprocess: ['Counter1:', 0, 'Counter2:', 10]
Closed stdin and out for subprocess. Terminating.
Subprocess started!
Received in subprocess: ['Counter1:', 0, 'Counter2:', 1]
Received in subprocess: ['Counter1:', 0, 'Counter2:', 2]
Received in subprocess: ['Counter1:', 0, 'Counter2:', 3]
Received in subprocess: ['Counter1:', 0, 'Counter2:', 4]
Received in subprocess: ['Counter1:', 0, 'Counter2:', 5]
Received in subprocess: ['Counter1:', 0, 'Counter2:', 6]
Received in subprocess: ['Counter1:', 0, 'Counter2:', 7]
Received in subprocess: ['Counter1:', 0, 'Counter2:', 8]
Received in subprocess: ['Counter1:', 0, 'Counter2:', 9]
Received in subprocess: ['Counter1:', 0, 'Counter2:', 10]
Parent has closed connection. Terminating.
Hier mal der modizifierte Code:
test1.py

Code: Alles auswählen

import sys, pickle

# Daten lesen und gleich wieder dumpen.
sys.stderr.write("Subprocess started!\n")
while True:
    try:
        data = pickle.load(sys.stdin)
        sys.stderr.write("Received in subprocess: %r\n" % data)
    except EOFError:
        sys.stderr.write("Parent has closed connection. Terminating.\n")
        break

    data[1] = data[1] + 1 # verändern des Counter1

    pickle.dump(data,sys.stdout, protocol=pickle.HIGHEST_PROTOCOL)
    sys.stdout.flush()
test2.py

Code: Alles auswählen

import sys, pickle, subprocess

proc = subprocess.Popen(["python","test1.py"],0,None,
                        subprocess.PIPE,subprocess.PIPE,None,
                        universal_newlines=True)

data = ["Counter1:",0,"Counter2:",0]
for in range(10):

    data[3] = data[3] + 1 # verändern des Counter2

    print "Writing data to subprocess:", data
    pickle.dump(data,proc.stdin, protocol=pickle.HIGHEST_PROTOCOL)
    data = pickle.load(proc.stdout)
    print "Got data from subprocess:", data

proc.stdin.close()
proc.stdout.close()

print "Closed stdin and out for subprocess. Terminating."

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

modelnine hat geschrieben:Informationen dazu gibts unter:

http://www.python.org/doc/faq/windows.h ... t-or-win95
Das betrifft allerdings nur Win9x + NT... Ich denke mal unter 2000/XP sieht's anders aus :lol:

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Das sollte eigentlich nicht gehen, aber egal. Und: unter XP/2000 sieht's nicht anders aus, die Verhalten sich genau wie NT.

Der wichtige Unterschied zwischen meinem letzten Post und dem ersten war dass man python mit "-u" aufgerufen hat als Parameter, siehe dazu auch den geposteten Link. Der bewirkt nämlich dass der Unterprozess (also python) stdin und out im binary mode aufmacht, sonst sind die nämlich text-mode, und dann kommt so scheiße wie \n -> \r\n o.Ä. rein.

universal_newlines braucht man dann logischerweise nicht, darf man sogar nicht setzen.

jens: guck Dir also noch mal genau mein Beispiel an und modifizier dann Deines soweit, das ist die richtige Lösung.

--- Heiko.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Also ich hab es jetzt nochmal getestet... Es ist egal ob man dem Interpreter mit -u startet und/oder universal_newlines=True ist ;)

Ist kein -u und kein universal_newlines=True dann kommt es zu den Fehlern!

EDIT: Anders sieht es mit SciTE aus... Wenn das das "-u" fehlt, dann kommen die Ausgaben durcheinader, wie ich es gepostet hab... Mit "-u" ist alles genau so, wie es soll... Somit ist "-u" doch ein muß ;)

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Also hier nochmal der Code, der anscheinent überall klappt:
test2.py

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import sys, pickle, subprocess

proc = subprocess.Popen(["python","-u", "test1.py"],0,None,
                        subprocess.PIPE,subprocess.PIPE,None)

data = ["Counter1:",0,"Counter2:",0]
for i in range(10):

    data[3] = data[3] + 1 # verändern des Counter2

    print "Writing data to subprocess:", data
    pickle.dump(data,proc.stdin, pickle.HIGHEST_PROTOCOL)
    data = pickle.load(proc.stdout)
    print "Got data from subprocess:", data

proc.stdin.close()
proc.stdout.close()

print "Closed stdin and out for subprocess. Terminating."
test1.py

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import sys, pickle

# Daten lesen und gleich wieder dumpen.
sys.stderr.write("Subprocess started!\n")
while True:
    try:
        data = pickle.load(sys.stdin)
        sys.stderr.write("Received in subprocess: %r\n" % data)
    except EOFError:
        sys.stderr.write("Parent has closed connection. Terminating.\n")
        break

    data[1] = data[1] + 1 # verändern des Counter1

    pickle.dump(data,sys.stdout, pickle.HIGHEST_PROTOCOL)
    sys.stdout.flush()
Die Frage ist dennoch, ob sowas Sinnvoll ist... Denn es wird wahrscheinlich schweg mit dem debuggen, denke ich...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten