Dentro de Linux, hay un archivo, /sys/kernel/debug/tracing/trace_pipe , que como dice el nombre, es una tubería. Entonces, digamos que quiero leer los primeros 50 bytes usando Python, y ejecuto el siguiente código:
$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> Podemos ver que la apertura del archivo es rápida (si tenemos los permisos de superusuario); sin embargo, si el archivo trace_pipe está vacío en ese momento, simplemente se bloqueará (e incluso si hay contenido, el contenido se volcará hasta que haya no más, y luego nuevamente el archivo se bloqueará). Luego tengo que presionar Ctrl - C para interrumpir el script de Python con KeyboardInterrupt ...
¿Cómo puedo hacer que Python 2.7 haga una lectura con tiempo de espera?
Es decir, quiero indicarle a Python que "intente leer 50 bytes de este archivo; si no tiene éxito después de un segundo, ríndase y regrese" .
Usar
os.read(f.fileno(), 50)en cambio. Eso no espera hasta que se haya leído la cantidad especificada de bytes, sino que regresa cuando ha leído algo (como máximo la cantidad especificada de bytes).
Esto no resuelve su problema en caso de que no tenga nada que leer de esa tubería. En ese caso, debe usar select from the module select para probar si hay algo para leer.
EDITAR:
Prueba de entrada vacía con 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 casef = os.open("/sys/kernel/debug/tracing/trace_pipe", os.O_RDONLY|os.O_NONBLOCK)Debería evitar el bloqueo (solo funciona en Unix). No es necesario seleccionar aquí.
Solo agregando esto como nota, para un mejor formato:
La respuesta de @Alfe en mi caso:
$ 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() 'Si hay algo en el archivo, obtengo una respuesta como:
<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 sSi no hay nada en el archivo, obtengo:
<open file '/sys/kernel/debug/tracing/trace_pipe', mode 'r' at 0xb7831e90> [] [] [] timed out Tenga en cuenta que la documentación de select no es explícita en cuanto a que el parámetro de timeout de espera está en segundos, pero los valores de coma flotante (por ejemplo, 0.5) también funcionan.
Respuesta de @GabiMe:
$ 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() 'Si hay algo en el archivo, obtengo una respuesta como:
<open file '<fdopen>', mode 'r' at 0xb77b6e90> A bash-13777 [000] 13694.404519: sys_exi B Timer-31065 [001] 13694.404830: sys_exiSi no hay nada en el archivo, obtengo:
<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 ... entonces uno debe ejecutar esto en un bloque de try , para capturar el IOError , si no hay nada en el archivo... (tanto os.read como f.read generarán esta excepción)