2013-09-23 46 views
1

我正嘗試使用這一行應該打印所有行被添加到文件/var/log/messages.logsys.stdin多長時間產生一次數據?

sudo tail -f /var/log/messages.log | python2 -c 'exec("import sys\n\nfor line in sys.stdin:\n\tprint line")' 

爲增加可讀性,Python代碼是:

import sys 

for line in sys.stdin: 
     print line 

如果我一個行添加到/var/log/messages.log,我沒有看到越來越打印任何東西。但是,如果我添加大量數據,我開始獲得輸出。

是否有定義的行爲,發生器sys.stdin生成data的頻率?

PS:我的最終目標是瞭解one-liner,它輸出每秒輸入到python程序的行數。

編輯:假設解釋者每隔一秒就會越過這條線if t > e:

+0

在我的機器上,鏈接的單行程不能很好地工作。它遭受的問題與您的代碼完全相同 - 報告延遲到file.next()的預讀緩衝區滿足爲止。 –

+0

這不是真正的單線順便說一句。 –

+0

P.S.我已經更新了我的答案,以解釋爲什麼「一班」的工作方式如此;然而,至少在我的電腦上,它仍然遭受同樣的輸入緩衝問題,就像@Robᵩ報道的那樣。 –

回答

2

OK,所以這裏是爲我工作:

import sys 

while True: 
    print sys.stdin.readline() 

而且隨着python -u ...啓動腳本。

我承認托馬斯給其他主題的鏈接幫助我發現.readline()應該直接用於-u以產生任何效果。

說明:-u禁用stdin中的過程級的緩衝(如在「標準輸入」,而不是sys.stdin對象特異性),以及使用的.readline()代替for line in sys.stdin避免了sys.stdin內部緩衝。

UPDATE:至於你對這個one-liner的問題:「如何是它假定譯員將越過這條線if t > e:每隔一秒」 ......「一個班輪」下的觀察是:

import sys, time 
l = 0 
e = int(time.time()) 
for line in sys.stdin: 
    t = int(time.time()) 
    l += 1 
    if t > e: 
     e = t 
     print l 
     l = 0 

time.time()以秒爲單位返回當前時間爲float;將其轉換爲int基本上只是將其舍入到滿秒;並且第一時刻int(time.time())大於e,它也被設置爲int(time.time()),幾乎是一秒鐘過去了。

但該片段仍然遭受完全相同的輸入緩衝問題您的原始片段;另外,它在沒有-u標誌的情況下被調用,所以我無法想象爲什麼它可以在任何系統上可靠地工作,除非該系統上的緩衝語義在Python進程STDIN級別以及sys.stdin的實現中都不同。

+0

我的問題的一部分還在於,單線程是如何完美工作的? –

+1

重要線索(http://docs.python.org/2/library/stdtypes.html#bltin-file-objects):「*爲了使循環成爲循環遍歷文件行的最有效方式(一個非常常見的操作),next()方法使用一個隱藏的預讀緩衝區。由於使用預讀緩衝區,將next()與其他文件方法(如readline())結合使用並不正確。但是,使用seek()將文件重新定位到絕對位置將刷新預讀緩衝區。*「 –

+1

@shadyabhi:'-u'禁用進程級緩衝'stdin'(如」標準輸入「和而不是'sys.stdin'對象),而使用'.readline()'而不是'sys.stdin'中的行來避免'sys.stdin'的內部緩衝。 –

2

stdin被緩衝。

在Python 2中,您可以在啓動Python時使用-u標誌或設置PYTHONUNBUFFERED環境變量來禁用緩衝。

有一些注意事項要留意,但this answer has the most detail

+0

已經嘗試'-u'-似乎沒有任何效果。 –

相關問題