2015-09-29 98 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