在Python中读取带超时的文件

时间:2014-01-29 11:13:31

标签: python linux python-2.7

在Linux中,有一个文件/sys/kernel/debug/tracing/trace_pipe,正如其名称所示,是一个管道。所以,假设我想用Python读取它的前50个字节 - 我运行以下代码:

$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>

我们可以看到打开文件的速度很快(如果我们拥有超级用户权限) - 但是,如果此时trace_pipe文件为空,它将只是阻止(即使有内容,内容将被丢弃,直到没有更多,然后文件将被阻止)。然后我必须按 Ctrl - C KeyboardInterrupt ...

中断Python脚本

如何让Python 2.7执行超时读取?

也就是说,我想指示Python “尝试从此文件中读取50个字节;如果一秒后没有成功,请放弃并返回”

3 个答案:

答案 0 :(得分:18)

使用

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

代替。这不会等到读取指定的字节数,而是在读取任何内容时返回(最多指定的字节数)。

如果您从该管道中读取 nothing ,则无法解决您的问题。在这种情况下,您应该使用模块select中的select测试是否有需要阅读的内容。

编辑:

使用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

答案 1 :(得分:12)

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

应该阻止阻止(仅适用于Unix) 这里不需要选择..

答案 2 :(得分:2)

只需将其添加为注释即可获得更好的格式:

@ Alfe在我的案例中回答:

$ 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() '

如果文件中有内容,我会得到如下响应:

<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

如果文件中没有任何内容,我会:

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

请注意,select文档并未明确timeout参数以秒为单位 - 但浮点值(例如0.5)也有效。

@ 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() '

如果文件中有内容,我会得到如下响应:

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

如果文件中没有任何内容,我会:

<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

...所以必须在try块中运行此项,以便在文件中没有任何内容时捕获IOError ...(os.read和{{1}将引发此异常)