2014-11-06 90 views
1

目前我使用子進程讀取從卡塔利娜日誌文件數據:蟒蛇:獲得下一個項目,而在for循環

text = subprocess.popen(" cat filename.txt",shell=True, stdout=subprocess.PIPE,stderr=subprocess.STDOUT) 

文本格式將有線路組按以下格式:

INFO timestamp | Inbound Message 
ID: 1234 
Address: http://www.google.com 

我希望做的是沿着線的東西:

for line in text.stdout.readlines(): 
    if line.split()[line.count(' ')-2] == "Inbound": 
     time = "%s %s"%(line.split()[1],re.sub(',','.',line.split()[2])) 
     id = text.stdout.readline().split()[1] 
     address = text.stdout.readline().split[1] 

但是,這個功能似乎並沒有因爲readline()不會拉動文本中的下一行。

+0

所以你想要入站後的線路或只是所有的ID和地址配對?另外你爲什麼用貓打開並閱讀文件? – 2014-11-06 00:10:43

+0

(很)無用的貓用]? ...'open('filename.txt','r')。readlines()'?有什麼問題? – Carpetsmoker 2014-11-06 00:14:06

回答

2

你的問題是你已經調用readlines()來讀取所有的標準輸出直到最後到一個大列表循環它。因此,當您再次致電stdout.readline()時,它不會返回任何內容,因爲您已經閱讀了所有內容。

這裏的答案是不使用readlines()並直接遍歷文件:*

for line in text.stdout: 

現在,通過每一次循環中,text.stdout的文件指針當前行之後指點,所以text.stdout.readline()會給你下一行(並消耗它,所以它不會通過循環下一次顯示)。

在這裏使用next(text.stdout)可能更具可讀性,因爲這樣可以更明確地表明您使用的循環迭代器與for循環相同,但它的效果也是一樣的。

這就是說,試圖從一個循環內消耗一個迭代器也是消耗它的一個很好的方法來迷惑自己。你可能想考慮回退一個級別,詢問是否有更清晰的方法來解決這個問題。


*其實,「不使用readlines()」幾乎總是答案,或至少是有益的改進,涉及readlines()任何代碼。

1

不要使用子進程來獲取文件使用open的內容,然後在文件對象調用next文件對象上站上罰球線後的兩行包含Inbound迭代:

with open("filename.txt") as f: 
    for line in f: 
     if "| Inbound" in line: 
      time = line.split()[1] # split Inbound line 
      id = next(f).split()[1] # split following line with id 
      address = next(f).split()[1] # split next line containing address 
      print(time,id,address) 
('timestamp', '1234', 'http://www.google.com') 
1
with open('filename.txt') as lines: 
    for line in lines: 
     if line.endswith(' | Inbound Message\n'): 
      timestamp = line.split()[1] 
      ident = next(lines).split()[1] 
      address = next(lines).split()[1] 
      print timestamp, ident, address