Frage

Ich habe vor kurzem brauchte ein Skript zu schreiben, die eine os.fork führt () in zwei Prozesse aufgeteilt. Das Kind Prozess wird zu einem Server-Prozess und übergibt Daten an den übergeordneten Prozess ein Rohr mit erstellt mit os.pipe () . Das Kind schließt das 'r' Ende des Rohres und die übergeordneten schließt das 'w' Ende des Rohres, wie üblich. Ich konvertiere die Erträge aus dem Rohr () in Dateiobjekte mit os.fdopen .

Das Problem, das ich habe, ist dies: Der Prozess erfolgreich Gabeln, und das Kind wird zu einem Server. Alles funktioniert gut und das Kind dutifully schreibt Daten in das offenen 'w' Ende des Rohres. Leider ist die Mutter Ende des Rohres hat zwei seltsame Dinge:
A) Es blockiert auf der read() Operation auf dem 'r' Ende des Rohres.
Zweitens ist es nicht alle Daten zu lesen, die auf dem Rohr genommen wurden, es sei denn das 'w' Ende vollständig geschlossen ist.

Ich dachte sofort, dass Pufferung war das Problem und hinzugefügt pipe.flush () Anrufe, aber diese nicht helfen.

Kann jemand etwas Licht auf, warum die Daten bis zum Schreibende erscheint nicht vollständig geschlossen ist? Und gibt es eine Strategie, um die read() Anruf nicht blockierende zu machen?

Dies ist mein erstes Python-Programm, das gegabelt oder verwendet, um Rohre, so vergib mich, wenn ich einen einfachen Fehler gemacht habe.

War es hilfreich?

Lösung

Sind Sie mit read (), ohne eine Bildgröße oder das Rohr als Iterator Behandlung (for line in f)? Wenn ja, das ist wahrscheinlich die Ursache des Problems - read () definiert ist, bis zum Ende der Datei zu lesen, vor der Rückkehr, und nicht nur lesen, was zum Lesen zur Verfügung. Das bedeutet, es wird blockiert, bis das Kind nahe () aufruft.

Im Beispielcode verknüpft, das ist in Ordnung - die Eltern in einer blockierenden Weise wirken, und nur mit dem Kind zu Isolationszwecken. Wenn Sie weitermachen wollen, dann verwenden Sie entweder nicht-blockierende IO wie im Code, den Sie geschrieben (aber mit Halb vollständigen Daten umgehen hergestellt werden) oder in Stücken (zB r.read (Größe) oder r.readline lesen () ), die nur blockiert, bis eine bestimmte Größe / Zeile gelesen wurde. (Sie werden noch bündig auf das Kind nennen müssen)

Es sieht aus wie das Rohr zu behandeln, als ein Iterator sowie einige weitere Puffer verwendet, für „for line in r:“ können Sie nicht geben, was Sie wollen, wenn Sie jede Zeile werden sofort verbraucht müssen. Es kann möglich sein, dies zu deaktivieren, aber nur 0 für die Puffergröße in fdopen Angabe nicht ausreichend zu sein scheint.

Heres einige Beispielcode, die funktionieren sollte:

import os, sys, time

r,w=os.pipe()
r,w=os.fdopen(r,'r',0), os.fdopen(w,'w',0)

pid = os.fork()
if pid:          # Parent
    w.close()
    while 1:
        data=r.readline()
        if not data: break
        print "parent read: " + data.strip()
else:           # Child
    r.close()
    for i in range(10):
        print >>w, "line %s" % i
        w.flush()
        time.sleep(1)

Andere Tipps

Mit

fcntl.fcntl(readPipe, fcntl.F_SETFL, os.O_NONBLOCK)

Vor dem Lese () aufgerufen wird gelöst beiden Probleme. Die read () Anruf wird nicht mehr blockiert und die Daten werden nach nur einem Flush () auf dem Schreibende erscheinen.

Ich sehe das Problem der Blockierung gelöst haben i / o und Pufferung.

Ein Hinweis, wenn Sie einen anderen Ansatz versuchen entscheiden: Unterprozess ist das Äquivalent / Ersatz für die fork / exec Idiom. Es scheint, wie das ist nicht das, was Sie tun: Sie haben nur eine Gabel (kein exec) und den Austausch von Daten zwischen den beiden Prozessen - in diesem Fall die multiprocessing Modul (in Python 2.6+) wäre eine bessere Passform sein.

Die „Eltern“ vs. „Kind“ Teil der Gabel in einer Python-Anwendung ist albern. Es ist ein Erbe von 16-Bit-Unix-Tagen. Es ist eine Affektiertheit von einem Tag, an dem fork / exec und exec waren wichtige Dinge, die die meisten von einem winzigen Prozessor zu machen.

Brechen Sie Ihre Python-Code in zwei separate Teile. Eltern und Kind

Die Mutter Teil sollte verwenden subprocess das Kind Teil laufen.

Eine Gabel und exec können irgendwo in dort passieren - aber Sie brauchen nicht zu kümmern

.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top