2014-01-29 77 views
12

在Linux中,有一個文件/sys/kernel/debug/tracing/trace_pipe,正如其名稱所示,它是一個管道。所以,讓我們說,我想用Python從它讀取的第一個50個字節 - 我運行下面的代碼:在Python中讀取超時的文件

$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鍵 - Ç中斷Python腳本與KeyboardInterrupt ...

我怎麼能有Python 2.7版做了讀取與超時?

也就是說,我想指示Python來「嘗試從這個文件中讀取50個字節;如果你沒有在一秒鐘後不成功,就放棄並返回」

回答

15

使用

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

代替。這不會等到指定的字節數已被讀取,而是在讀取任何內容(至多指定的字節數)時返回。

如果您有什麼也沒有從管道讀取,這並不解決您的問題。在這種情況下,您應該使用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 
+0

非常感謝,@Alfe - 我忘記了'os.read' ...但是,我確實想要主要處理這個案例當我沒有什麼可讀的時候!感謝您指出['select'(http://docs.python.org/2/library/select.html) - 但對我來說,什麼是'rlist','wlist',或'xlist'?如果我沒有什麼可讀的,我應該期待什麼?當我使用它時,「select」告訴我可用的字節總數,或者「至少有1個字節可用」? – sdaau

+1

請參閱我的編輯關於'選擇'如何使用它。 'select'返回你交給它的流集合的子集。你的情況很簡單,你只有一個流只能讀取,所以一切都空着。給一個0超時,所以它永遠不會_wait_,然後測試是否有'f'可讀的東西。如果是這樣,至少可以讀取一個字節。然後從該流中讀取至少一個字節和最多50個字節(如您指定的那樣)。 – Alfe

+1

啊,你應該注意的一件事情是,通常情況下,除非有閱讀器讀取它,否則管道不能寫入。所以你將永遠不會有任何東西在等待在管道中讀取。也許你應該使用超時有點大於0 ;-) – Alfe

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

應防止阻塞無需選擇在這裏(只在Unix的作品).. ..

+3

非常感謝的是,@GabiMe;並沒有意識到'os.open'提供了特定於平臺的選項!我想搬到這裏的接受,但我會繼續在第一個答案,因爲這種方法,人們還需要知道fdopen'的',並檢查異常,如果有什麼文件中(見在我的帖子下面編輯)。再次感謝 - 歡呼! – sdaau

3

只需添加此注意,爲更好的格式化:

@ 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.readf.read都會引發此異常)

+0

從您鏈接到有關'select'的實況:»可選的超時參數指定超時以秒爲一個浮點數«爲什麼你認爲它沒有說的'timeout'參數以秒爲單位。? – Alfe