2014-01-29 14 views
12

In Linux gibt es eine Datei, /sys/kernel/debug/tracing/trace_pipe, die, wie der Name sagt, eine Pipe ist. Also, lassen Sie uns sagen, dass ich die ersten 50 Bytes aus es mit Python lesen wollen - und ich den folgenden Code:Datei mit Timeout in Python lesen

$sudo python -c 'f=open("/sys/kernel/debug/tracing/trace_pipe","r"); print f; print f.read(50); f.close()<br> 
<open file '/sys/kernel/debug/tracing/trace_pipe', mode 'r' at 0xb7757e90> 

Wir können sehen, dass die Datei zu öffnen schnell geht (wenn wir die Super-User-Berechtigungen haben) - aber Wenn die trace_pipe Datei zu diesem Zeitpunkt leer ist, wird sie einfach blockiert (und selbst wenn Inhalt vorhanden ist, wird der Inhalt ausgegeben, bis es nicht mehr vorhanden ist, und dann wird die Datei wieder blockiert). Dann habe ich Ctrl drücken - C den Python-Skript zu unterbrechen, mit einem KeyboardInterrupt ...

Wie kann ich Python 2.7 mit Timeout einen Lese tun?

Das heißt, ich will Python instruieren „versuchen 50 Bytes aus dieser Datei lesen, wenn Sie nicht nach einer Sekunde gelingt es, aufgeben und zurückkehren“?

Antwort

15

Verwenden

os.read(f.fileno(), 50) 

statt. Dieser wartet nicht, bis die angegebene Anzahl von Bytes gelesen wurde, kehrt aber zurück, wenn er etwas gelesen hat (höchstens die angegebene Anzahl an Bytes).

Dies löst Ihr Problem nicht, wenn Sie nichts aus dieser Pipe lesen. In diesem Fall sollten Sie select vom Modul select bis Test verwenden, ob etwas zu lesen ist.

EDIT:

Testen für leere Eingabe mit select:

import select 
r, w, e = select.select([ f ], [], [], 0) 
if f in r: 
    print os.read(f.fileno(), 50) 
else: 
    print "nothing available!" # or just ignore that case 
+0

Vielen Dank dafür, @Alfe - Ich habe 'os.read' vergessen ... Allerdings möchte ich in erster Linie den Fall behandeln wenn ich nichts zu lesen habe! Danke, dass Sie ['select'] notiert haben (http://docs.python.org/2/library/select.html) - aber in meinem Fall, was ist' rlist', 'wlist' oder' xlist'? Was sollte ich erwarten, wenn ich nichts zu lesen habe? Gibt 'select' an, wieviel Bytes verfügbar sind, wenn ich es benutze oder nur" mindestens 1 Byte verfügbar ist "? – sdaau

+1

Siehe meine EDIT über 'Select' auf, wie man es benutzt. 'select' gibt Subsets der Datenströme zurück, die Sie ihm übergeben haben. Ihr Fall ist simpel, Sie haben nur einen Stream, von dem Sie nur lesen möchten, also lassen Sie alles andere leer. Geben Sie eine Zeitüberschreitung von 0 ein, so dass es für nichts _wait_ erwartet, und testen Sie dann, ob etwas von "f" lesbar ist. Wenn ja, kann mindestens ein Byte gelesen werden. Lesen Sie dann mindestens dieses eine Byte und höchstens 50 Byte (wie Sie angegeben haben) aus diesem Stream. – Alfe

+1

Ah, eine Sache, die Sie beachten sollten, ist die Tatsache, dass normalerweise eine Pipe geschrieben werden kann, es sei denn, dass ein Leser davon liest. Sie werden also nie etwas warten müssen, um in dieser Pipe gelesen zu werden. Vielleicht sollten Sie ein Timeout ein wenig größer als 0 verwenden ;-) – Alfe

11
f = os.open("/sys/kernel/debug/tracing/trace_pipe", os.O_RDONLY|os.O_NONBLOCK) 

Sollte blockiert (Arbeiten in nur Unix) verhindern .. Keine Notwendigkeit wählen hier ..

+3

Vielen Dank dafür, @GabiMe; war sich nicht bewusst, dass 'os.open' plattformspezifische Optionen bietet! Ich dachte daran, das Akzeptieren hier zu verschieben, aber ich werde die erste Antwort behalten, denn bei diesem Ansatz muss man auch 'fdopen' beachten und auch nach Ausnahmen suchen, wenn sich nichts in der Datei befindet (siehe die Bearbeitung in meinem Post unten). Nochmals vielen Dank - Prost! – sdaau

3

Fügen Sie dies einfach als Notiz hinzu, um eine bessere Formatierung zu erhalten:

@ Alfe Antwort in meinem Fall:

$ sudo python -c 'import os, select; 
f=open("/sys/kernel/debug/tracing/trace_pipe","r"); print f; 
rrdy, wrdy, xrdy = select.select([f], [], [], 1); print rrdy, wrdy, xrdy ; 
timeout= "timed out" if (rrdy==[]) else "" ; 
print timeout; 
print os.read(f.fileno(), 50) if timeout=="" else ""; 
f.close() ' 

Wenn es etwas in der Datei ist, bekomme ich Antwort wie:

<open file '/sys/kernel/debug/tracing/trace_pipe', mode 'r' at 0xb76f0e90> 
[<open file '/sys/kernel/debug/tracing/trace_pipe', mode 'r' at 0xb76f0e90>] [] [] 

      Xorg-1033 [001] 12570.075859: <user s 

Wenn es nichts in der Datei ist, die ich erhalten:

<open file '/sys/kernel/debug/tracing/trace_pipe', mode 'r' at 0xb7831e90> 
[] [] [] 
timed out 

Beachten Sie, dass die select Dokumentation nicht explizit ist, dass der timeout Parameter in Sekunden ist - aber diese Gleitkommawerte (z. B. 0,5) auch arbeiten.

@ GabiMe Antwort:

$ sudo python -c 'import os; 
filno = os.open("/sys/kernel/debug/tracing/trace_pipe", os.O_RDONLY|os.O_NONBLOCK); 
f=os.fdopen(filno, "r"); print f; 
print "A", f.read(50); 
print "B", os.read(f.fileno(), 50); 
f.close() ' 

Wenn etwas in der Datei gibt es, bekomme ich Antwort wie:

<open file '<fdopen>', mode 'r' at 0xb77b6e90> 
A    bash-13777 [000] 13694.404519: sys_exi 
B   Timer-31065 [001] 13694.404830: sys_exi 

Wenn es nichts in der Datei ist, die ich erhalten:

<open file '<fdopen>', mode 'r' at 0xb77c1e90> 
A 
Traceback (most recent call last): 
    File "<string>", line 1, in <module> 
IOError: [Errno 11] Resource temporarily unavailable 

... also muss man das in einem try Block laufen lassen, um die IOError zu fangen, wenn da ist nichts in der Datei ... (sowohl os.read als auch f.read werden diese Ausnahme auslösen)

+0

Aus der Doku, mit der Sie über 'select' verknüpft haben:» Das optionale timeout-Argument gibt eine Zeitüberschreitung als Fließkommazahl in Sekunden an. «Warum glauben Sie nicht, dass der Parameter 'timeout' in Sekunden ist? – Alfe