2016-11-15 56 views
0

我想要執行一個任務,其中程序要經過一個目錄,輪流打開每個文件,並在任何其他事項之前檢查特定行。如果該行符合特定條件(即,它不匹配目錄中任何其他文件中的此行),則文件關閉,程序將移至下一個文件。Python - 如果文件滿足條件,則關閉文件

aps = [] 

import os 
for filename in os.listdir("C:\..."): 
    f = open(filename,"r") 
    (f.readline()) 
    (f.readline()) 
    ap = (f.readline()) 
    ap = ap.rstrip("\n") 
    aps.append(ap) 
    freqs = {} 
    for ap in aps: 
     freqs[ap] = freqs.get(ap, 0) + 1 
    for k, v in freqs.items(): 
     if v == 2: 
      f.close() 
     else: 

對於「別人:」我最初試圖「f.seek(0)」,但得到的Python的錯誤無​​法與一個封閉的文件工作。然後我再次嘗試'f = open(filename,「r」)',但是這樣做有點奇怪,因爲當我試圖通過這種方法打印第一行時,它會在瘋狂的循環中發送它並多次打印該行。

這是完成此任務的最佳方式嗎?如果不是,我怎麼才能使它工作?

非常感謝。

+0

'f.close'後面'else'分支的用途是什麼?你還需要從文件中讀取嗎? – sal

+0

您應該在關閉文件後添加一個「break」,以便它不會循環。 –

回答

2

請勿有條件地關閉文件。做你需要做的與打開的文件,然後在最後關閉它。隨着with構造文件將自動關閉:

for filename in os.listdir(path): 
    with open(filename) as f: 
     # do processing here 
     if positive_condition: 
      # do more processing 
1

這就是爲什麼你的代碼失敗。您在外部for循環之外初始化aps列表,以便它將包含循環的所有文件中的指定行。然後您的freqs字典重置爲您打開的每個文件爲空。

那麼這些行:

for ap in aps: 
    freqs[ap] = freqs.get(ap, 0) + 1 

環比已到目前爲止讀取,並計算頻率的每一行。這個問題是在內部進行循環:

for k, v in freqs.items(): 
    if v == 2: 
     f.close() 

這裏會發生什麼事是freqs有一組按鍵可能一樣大,你已經掛繞到目前爲止文件的數量,而你是通過每個鍵循環。因此,第一次鍵值爲2時,當前文件被關閉。但是循環繼續,所以下一次鍵值爲2時,python會嘗試關閉文件,但它已經關閉。

最簡單的修復方法是在f.close()之後添加break。但是有更好的方法來構造這些代碼。

一個是總是用with命令打開一個文件,除非你有充分的理由不這樣做。所以:

with open(filename,"r") as f: 
    #code 

這樣,當你完成它的文件將自動關閉。

我假設您循環遍歷文件的順序並不重要,並且您希望頻率測試包括所有文件,而不僅僅是迄今爲止打開的文件。在這種情況下,可能會更容易循環兩次,一次用於組合頻率字典,另一次用於對要滿足頻率要求的文件做任何想做的事情。

aps = [] 
freqs = {} 
# First loop to read the important line from all files 
for filename in os.listdir("C:\..."): 
    with open(filename,"r") as f: 
     f.readline() 
     f.readline() 
     ap = f.readline().rstrip("\n") 
     aps.append(ap) 
# Populate the dictionary 
for ap in aps: 
    freqs[ap] = freqs.get(ap, 0) + 1 
# Second loop to handle the important cases 
for filename in os.listdir("C:\..."): 
    with open(filename,"r") as f: 
     f.readline() 
     f.readline() 
     ap = f.readline().rstrip("\n") 
     if freqs[ap] != 2: 
      #do whatever 

我強烈懷疑有更高效和pythonic方式到達那裏,但這是我最好的想法。