2015-09-29 99 views
0

我正在執行下面的python代碼。python的Windows磁盤使用問題

我在一個文件夾(「文章」)上運行它有幾百個子文件夾和240,226個文件。

我正在計時執行。起初時間非常穩定,但在100,000個文件後變爲非線性。現在時間(我以10,000個文件間隔計時)可以在30,000左右(或不是)之後變爲非線性。

我有任務管理器打開,並通過python.exe關聯減速到99%的磁盤使用情況。我完成了gc-collect()。 dels等,關閉Windows索引。我已重新啓動Windows,清空垃圾(我有幾百GB免費)。沒有什麼幫助,如果有的話,磁盤使用似乎越來越不穩定。

很抱歉的長期職位 - 感謝您的幫助

def get_filenames(): 
    for (dirpath, dirnames, filenames) in os.walk("articles/"): 
     dirs.extend(dirnames) 

    for dir in dirs: 
     path = "articles" + "\\" + dir   
     nxml_files.extend(glob.glob(path + "/*.nxml")) 

    return nxml_files 

def extract_text_from_files(nxml_files): 
    for nxml_file in nxml_files:  
     fast_parse(nxml_file) 

def fast_parse(infile): 
    file = open(infile,"r") 
    filetext = file.read() 
    tag_breaks = filetext.split('><') 
    paragraphs = [tag_break.strip('p>').strip('</') for tag_break in tag_breaks if tag_break.startswith('p>')] 

def run_files(): 
    nxml_files = get_filenames() 
    extract_text_from_files(nxml_files) 

if __name__ == "__main__":  
    run_files() 
+0

如果可以,請升級到Python 3.5;你的代碼似乎沒有使用特定的版本特性,並且使用新的['os.scandir']重新實現了'os.walk'(https://docs.python.org/3/library/os.html#os .scandir)功能。雖然'os.walk'不通過它的接口向你提供免費的'stat'信息,它執行的磁盤I/O要少得多;在Python <= 3.4時,它必須讀取文件的完整列表(少量I/O操作,搜索次數有限),然後將所有文件和目錄統統分開(在你的情況下,大約100,000次隨機讀取) 。使用'os.scandir'消除〜100,000'stats'。 – ShadowRanger

+0

根據[Python 3.5發行說明](https://docs.python.org/3/whatsnew/3.5.html#whatsnew-pep-471),'os.scandir'在'os.walk'中使用無縫地將Windows系統中「os.walk」的速度提高了7-20倍。這是巨大的,如果你掃描了超過十萬個文件,你幾乎肯定會從加速中受益。 – ShadowRanger

回答

0

有一些東西是可以優化。

首先,你打開文件,關閉它們。一個with open(...) as name:塊將很容易做到這一點。 BTW在Python 2 file中是變量名的不好選擇,它是內置函數的名字。

您可以通過進行字符串比較而不是glob來移除讀取的一張光盤。

最後但並非最不重要:os.walk聰明地吐出結果,所以不要將它們緩衝到列表中,處理一個循環內的所有內容。這將節省大量的內存。

這是我可以從代碼建議。有關導致I/O的原因的更多詳細信息,應使用分析。有關詳細信息,請參見https://docs.python.org/2/library/profile.html

+1

減少磁盤I/O的另一個機會:'os.walk'給出了被放棄的'filenames'的列表,''fnmatch']()會使用'glob.glob'來獲得一組經過濾的文件。 https://docs.python.org/3/library/fnmatch.html)可以用來直接過濾'filenames'並避免'glob.glob'中涉及的冗餘磁盤I/O。編輯:哎呀,我看你提到過。在這裏留下這個鏈接到'fnmatch'(這是'glob.glob'實際用於過濾的東西,所以它可以精確地在已知的文件名列表上模擬'glob')。 – ShadowRanger

+0

是的,那將是我寫的一個選擇。我把它交給OP來測試哪個更快更適合。 –

+0

感謝您的建議,他們都做了這些,磁盤上的行爲也一樣(注意代碼獲取文件名是一次性命中)我認爲主要問題是爲什麼extract_text_from_files代碼(即使是使用file.close())不正確吮吸磁盤? – sandyshores