Python-warten Sie, bis die Daten im sys.stdin
mein problem ist Folgendes:
Mein Python-Skript empfängt die Daten via sys.stdin, aber es muss warten, bis neue Daten verfügbar sind, wird auf sys.stdin.
Wie beschrieben in der manpage von python, habe ich den folgenden code verwenden, aber es ist völlig überlastet meine cpu.
#!/usr/bin/python -u
import sys
while 1:
for line in sys.stdin.readlines():
do something useful
Ist es eine gute Art und Weise zu lösen, die eine hohe cpu-Auslastung?
Edit:
Alle Ihre Lösungen funktionieren nicht.
Ich gebe dir genau mein problem.
Können Sie die Konfiguration des apache2-daemon, er sendet jeden logline, um ein Programm und nicht zum schreiben in ein logfile.
Dieser sieht etwas so aus:
CustomLog "|/usr/bin/python -u /usr/local/bin/client.py" combined
Apache2 erwartet von meinem Skript, es läuft immer, wartet auf Daten auf sys.stdin und analysiert Sie dann die Daten.
Wenn ich nur eine for-Schleife verwenden Sie das Skript wird verlassen, denn an einem Punkt gibt es keine Daten in der sys.stdin und apache2 sagen ohh Ihr Skript beendet unerwartet.
Wenn ich mit einer while-true-Schleife mein Skript verwendet 100% cpu-Auslastung.
Zunächst sollten Sie sich bewusst sein, der Unterschied zwischen
readline()
und readlines()
. readlines()
liest alle Eingaben von stdin bis EOF (im Grunde Berufung read()
dann teilen durch newline). Das heißt, Sie kommen für die erste Zeit, wenn stdin geschlossen wurde. Künftige Aufrufe readlines()
(oder read()
und readline()
) auf stdin zurück []
(oder ""
für read/readline). Empfohlene Lektüre: docs.python.org/2/tutorial/inputoutput.html unix.stackexchange.com/questions/103885/...InformationsquelleAutor Abalus | 2011-08-14
Du musst angemeldet sein, um einen Kommentar abzugeben.
Folgenden soll nur funktionieren.
Begründung:
Den code iteriert durch Zeilen in der Standardeingabe, wie Sie kommen in. Wenn der stream noch offen ist, aber es ist nicht eine komplette Zeile dann die Schleife hängen, bis entweder ein newline-Zeichen gefunden wird (und der gesamten Zeile zurückgegeben) oder der stream geschlossen wird (und das was auch immer ist Links im Puffer zurückgegeben wird).
Nachdem der stream geschlossen wurde, keine Daten mehr geschrieben werden können oder von stdin Lesen. Zeitraum.
Dem Grund, dass Ihr code war eine überlastung deiner cpu ist, dass wenn stdin geschlossen wurde, alle nachfolgenden versuche zur Iteration über stdin sofort zurück, ohne etwas zu tun. In Essenz, dein code entspricht der folgenden.
Vielleicht wäre es hilfreich, wenn Sie geschrieben, wie Sie schreiben Daten auf stdin.
EDIT:
Python wird (für die Zwecke von for-Schleifen, Iteratoren und readlines() betrachten Sie nun ein stream geschlossen wird, wenn es auf ein EOF-Zeichen. Sie können Fragen, python mehr Lesen Daten nach dieser, aber Sie können nicht verwenden eine der vorigen Methoden. Der python-Mann-Seite empfiehlt die Verwendung
Wenn ein EOF-Zeichen gefunden wird, wird readline wird ein leerer string zurückgegeben. Der nächste Aufruf von readline wird wie üblich funktionieren, wenn der stream noch offen ist. Sie können dies testen Sie sich selbst, indem Sie den Befehl in einem terminal. Drücken Sie Strg+D bewirkt, dass ein terminal zu schreiben, das EOF-Zeichen von stdin. Dadurch wird das erste Programm in diesem Beitrag zu beenden, aber das Letzte Programm wird fortgesetzt, um Daten zu Lesen, bis der Strom tatsächlich geschlossen. Das Letzte Programm, sollten Sie nicht 100% Ihrer CPU, da readline wartet, bis Daten vorhanden sind, die Rückkehr anstelle der Rückgabe ein leerer string.
Ich habe nur das problem einer busy-loop, wenn ich versuche readline aus einer Datei selbst. Aber beim Lesen von der Standardeingabe (stdin readline glücklich Blöcke.
Es gibt keine solche Sache wie eine "EOF-Zeichen", wenn ein Programm liest die Eingabe. Das OS fängt ^D und schließt die standard-Eingabe auf dem Programm, aber das Programm sieht nie die ^D. um dies Zu sehen, geben Sie
cat | wc
an der Eingabeaufforderung, und sofort mit ^D: Du wirst senden 0 Zeichen wc.Während du hast Recht, dass es keine wörtliche EOF-Zeichen in das Programm gelangt die Puffer, Sie sind falsch, zu behaupten, dass der stream geschlossen wird. Nach Ctrl-D eingegeben wird, wird beim nächsten Aufruf zugrunde liegenden Implementierung von read (C s Lesen) zurück, die EOF-makro. Nachfolgende Aufrufe von read wird den block, bis mehr Daten tritt in den Puffer. Also der stream nie wirklich schließt, es verwenden, informiert das Programm, dass alles, was auf der anderen Seite hat signalisiert seine Absicht, zu stoppen senden von Daten.
Auf meinem system (Ubuntu, Bildschirm).
sys.stdin.readline()
gibt nur leere Zeichenfolgen (d.h. EOF) habe ich einmal eingegeben <kbd>Strg+D</kbd> auch wenn ich versuche zu weiteren Eingang in diewhile True
SchleifeFunktioniert immer noch für mich. Ich bin mit Ubuntu 14 auf der virtualbox. Vielleicht könnten Sie versuchen, schriftlich
/proc/<pid>/fd/0
. Was passiert mit Ihrem Prozess? Bekommen Sie einen busy-loop, oder ist es einfach hängen?InformationsquelleAutor Dunes
Verwenden:
Nein. Die
for
Schleife hängen, warten auf weitere Daten. Wenn stdin geschlossen ist, wird die Schleife beendet, und das Skript wird mit der Ausführung fortfahren.Nein, es wird nicht funktionieren in meinem Fall. Mein Skript muss sich Verhalten, wie dieser code in perl #!/usr/bin/perl $| = 1; while (<STDIN>) { # ...hier beliebigen Transformationen und lookups... print $_; }
Versuchen Sie die Lösung und kommen wieder, wenn es ein problem gibt.
Tatsächlich, Sie sind beide falsch, in diesem Fall. Abalus: Das Skript endet nicht, wenn keine Daten vorhanden Links in stdin, so tut Sie das, wenn stdin geschlossen (obwohl es immer noch nicht für Sie arbeiten). @hamstergene: sys.stdin.readlines() nicht Rendite Zeilen, wie Sie gefunden werden, aber nur, wenn eine ctrl-d/EOF-Zeichen empfangen wird.
InformationsquelleAutor hamstergene
Gut stecke ich nun diese Zeilen von code.
Wenn ich nicht die Zeit verwendet werden.schlafen, das Skript erstellen Sie eine zu hohe Last auf cpu-Auslastung.
Wenn ich:
Wird es nur Parsen einer Zeile in Schritten von 0,01 Sekunden und die Leistung des apache2 ist wirklich schlecht
Vielen Dank für Eure Antworten.
beste Grüße
Abalus
InformationsquelleAutor Abalus
Diese funktioniert eigentlich einwandfrei (d.h. keine runnaway CPU) - wenn Sie rufen Sie das script von der shell aus, etwa so:
tail -f input-file | yourscript.py
Offensichtlich, dass es nicht ideal ist - da musst du dann schreiben alle relevanten stdout an die Datei -
aber es funktioniert ohne viel Aufwand!
Nämlich wegen der Verwendung
readline()
- ich denke:Wird es eigentlich aufhören und warten auf die Linie, bis Sie es bekommt mehr input.
Hoffe, das jemand hilft!
InformationsquelleAutor rm-vanda
Ich weiß, ich bringe alten Sachen zu Leben, aber dies scheint einer der top-hits auf das Thema. Die Lösung Abalus hat sich behoben hat Zeit.Schlaf pro Zyklus, unabhängig, ob die stdin ist tatsächlich leer und das Programm sollte im Leerlauf, oder es gibt eine Menge von Linien, die darauf warten bearbeitet zu werden. Eine kleine änderung macht das Programm verarbeitet alle Nachrichten, die schnell und warten nur, wenn die queue eigentlich leer. Also nur eine Linie, der ankommt, während der sleep-Periode können warten, die anderen werden verarbeitet, ohne jede Verzögerung.
Diesem Beispiel ist einfach die Umkehrung des input-lines, wenn Sie uns nur eine Zeile, reagiert er in einer zweiten (oder was immer Ihren Schlaf Zeitraum festgelegt ist), kann aber auch etwas wie "ls -l | reverse.py" wirklich schnell. Die CPU-Last für einen solchen Ansatz ist minimal, auch auf embedded-Systeme wie OpenWRT.
[::-1]
echo zurück, die stdin, anstatt die umgekehrte stdinInformationsquelleAutor Robert Špendl
Ich habe ein ähnliches problem, wo python wartet der sender (ob ein Benutzer oder einem anderen Programm) zu schließen-stream, bevor die Schleife beginnt mit der Ausführung. Ich hatte es gelöst, aber es war eindeutig nicht pythonic wie ich Sie hatte, zu greifen, zu
while True:
undsys.stdin.readline()
Schließlich fand ich einen Verweis in einem Kommentar in einem anderen post zu einem Modul namens io, die eine alternative zu den standard-Datei-Objekt. In Python 3 ist dies die Standardeinstellung. Von dem, was ich machen kann aus Python 2 behandelt stdin wie eine normale Datei und kein Strom.
Dieser versuchen, bei mir hat es geklappt:
InformationsquelleAutor NZJourneyMan
Habe ich kommen Sie zurück zum problem, nach einer langen Zeit. Das Problem scheint zu sein, dass Apache behandelt einen CustomLog-wie eine Datei-etwas, kann es öffnen, schreiben, schließen, und öffnen Sie dann zu einem späteren Zeitpunkt. Dies bewirkt, dass der empfangende Prozess gesagt werden, dass es den input-stream geschlossen wurde. Jedoch, das bedeutet nicht, dass die Prozesse input-stream kann nicht geschrieben werden, wieder, nur, dass je nachdem, welcher Prozess war das schreiben auf der Eingabe-stream wird nicht schriftlich an Sie wieder.
Die beste Möglichkeit, damit umzugehen, ist die Einrichtung eines handler und lassen Sie das OS kennen, rufen die handler, wenn Eingangs geschrieben, um die standard-Eingabe. Normalerweise sollten Sie vermeiden, schwer sich auf OS-signal event-handling, da Sie relativ teuer sind. Aber das kopieren von einem megabyte text folgenden nur produziert zwei SIGIO Ereignisse, so ist es in Ordnung in diesem Fall.
fancyecho.py
Wie können Sie dieses Spielzeug-Programm. Ausgangs-aufgeräumt wurde aufgrund der Verschränkung von input und output.
InformationsquelleAutor Dunes
Ich weiß, dies ist ein Alter thread, aber ich stolperte über das gleiche problem und herausgefunden, dass dies mehr damit zu tun, wie das Skript aufgerufen wurde eher als ein problem mit dem Skript. Zumindest in meinem Fall stellte sich heraus, dass das problem mit dem "system shell' auf debian (ie: was /bin/sh verlinkt ist, -- dies ist, was apache verwendet, um den Befehl auszuführen, die CustomLog-Rohre). Mehr info hier: http://www.spinics.net/lists/dash/msg00675.html
hth,
- steve
InformationsquelleAutor lonetwin
Dies funktioniert für mich, den code of /tmp/alog.py:
in http.conf:
Den Schlüssel nicht verwenden
Werden Sie warten, dort bekommen Sie nichts. Und für die Prüfung, denken Sie daran fout.flush(), sonst können Sie nicht sehen-Ausgang. Ich Teste auf fedora 15, python 2.7.1, Apache 2.2, nicht die cpu-Last, alog.py wird im Speicher vorhanden, wenn man ps man kann es sehen.
InformationsquelleAutor PasteBT