Stdin von einer Named Pipe bekommen


10

Ich versuche, Python in einem Terminalfenster auszuführen und es von einer Named Pipe umzuleiten. Dann schreibe ich in die Named Pipe in einem anderen Terminal und lasse diesen Befehl auf Python ausführen.

Terminal 1:

mkfifo p1
python < p1

Terminal 2:

echo -n "print \"Hello World\"" > p1

Was passiert ist - Python druckt Hello Worldund beendet. Was ich tun möchte, ist, Python am Laufen zu halten, um einen nächsten Befehl auszuführen. Wie mache ich das in der Shell?

Antworten:


10

Du musst

  • Führen Sie Python interaktiv aus, obwohl sein Standard kein Terminal ist: Verwenden Sie python -i
  • Halten Sie das Schreibende der Pipe offen, da Python sonst EOF erkennt und beendet.

So:

python -i < p1

Und anderswo:

exec 3> p1
echo '1j*1j' >&3
...
# and when done, close that file descriptor so python sees the EOF:
exec 3>&-

Vielen Dank! Es funktionierte. Ich weiß nicht, was Sie getan haben. Würden Sie Ihrer Antwort bitte einige Details hinzufügen, um zu erklären, was los ist? Was exec 3> p1macht und was ist &3& exec 3> &1? Vielen Dank.
Lord Loh.

1
Ihre Antwort erinnerte mich an dieses Banner - sphotos-b.xx.fbcdn.net/hphotos-ash4/… es ist das Titelbild eines Freundes auf Facebook :-)
Lord Loh.

Eine Frage, würde exec 3>&-das genauso funktionieren wie exec 3>&1hier?
Wildcard

1
@ Wildcard Ich vermute, ich wollte 3>&-hier schreiben . 3>&1würde auch funktionieren, macht aber wenig Sinn. Vielen Dank
Stéphane Chazelas

5

Sie können verwenden tail -f, um das FIFO nach dem Schreiben offen zu halten echo.

tail -n1 -f p1 | python

Warum das so ist

pythonliest aus p1. Wenn das Ende der Datei erreicht ist, hört es auf zu lesen. Dies ist ein normales Verhalten beim Lesen von Dateien, auch wenn es sich bei der Datei um eine Named Pipe handelt. tailMit dem -fFlag (Folgen) wird nach Erreichen des Endes weiter aus einer Datei gelesen.


Ich habe es echo "print \"Hello World\" " > p1im zweiten Terminal versucht und nichts ist passiert - aber das Terminal wurde auch nicht blockiert. Das Terminal mit Python blieb blockiert, bis ich ^ces und beende es und beende Python mit einer Tastatur-Interrupt-Meldung, die von Python angezeigt wird.
Lord Loh.

Ich habe diesen tail -fTrick verwendet, als ich das Block-Split-Teer-Archiv über eine Named Pipe entpackt habe. Es hat wunderbar funktioniert.
Mael

2

Sie müssen das gesamte Programm auf einmal senden.

Wenn Sie run aufrufen, python < p1wartet die Shell auf die Eingabe, bevor Sie Python aufrufen. Das heißt, dass Python nicht einmal ansatzweise die Ausführung überhaupt , bis der gesamte Datenstrom von dem Shell gelesen und dann in vollem Umfang weitergegeben wird python.

Selbst python -u p1wenn Sie stattdessen ausführen (dh ungepuffert und aus einer Datei lesen p1), pythonwird versucht, die gesamte Datei zu lesen, bevor sie ausgeführt wird.

Versuchen Sie dieses Experiment.

Terminal 1:

mkfifo p1
python < p1

Terminal 2:

cat > p1
print "Hello World"
print "Hello World"

Sie werden sehen, dass Sie mehrere Zeilen senden können, aber Python in Term 1 tut nichts. Drücken Sie nun ctrl+ D. Das gesamte Programm wird sofort ausgeführt.

Um zusammenzufassen, wenn Sie möchten, dass Python aus einer Pipe liest, müssen Sie das gesamte Programm senden. Sie können Python auf diese Weise nicht interaktiv verwenden.


1

Vielleicht ist der Heckansatz besser (flexibler), aber als Alternative:

{ echo -n "print \"Hello World\""; cat; } > p1

Das funktioniert nicht wie ich will. -nkönnte entfernt werden müssen. Und danach 0. Das Terminal mit dem echoBefehl wird blockiert 1. Python führt den Befehl erst aus, wenn ich ^cdas echoTerminal drücke und beide Prozesse beendet werden.
Lord Loh.

1
@ LordLoh. Kann ein Pufferproblem sein. Wahrscheinlich führt Python den Befehl aus, wenn genügend Ausgabe erstellt wurde, damit die erste Zeile schließlich in das FIFO geschrieben wird. Da es jedoch eine funktionierende Lösung gibt, wäre es nicht sinnvoll, sich um die Lösung dieses Problems zu bemühen.
Hauke ​​Laging
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.