性能:使用Python读取文件的最快方式
所以我有大约400个文件,大小从10kb到56mb不等,文件类型为.txt/.doc(x)/.pdf/.xml,我必须全部阅读。我的读入文件基本上是:性能:使用Python读取文件的最快方式,python,performance,io,Python,Performance,Io,所以我有大约400个文件,大小从10kb到56mb不等,文件类型为.txt/.doc(x)/.pdf/.xml,我必须全部阅读。我的读入文件基本上是: #for txt files with open("TXT\\" + path, 'r') as content_file: content = content_file.read().split(' ') #for doc files using pydoc contents = '\n'.join([para.text for pa
#for txt files
with open("TXT\\" + path, 'r') as content_file:
content = content_file.read().split(' ')
#for doc files using pydoc
contents = '\n'.join([para.text for para in doc.paragraphs]).encode("ascii","ignore").decode("utf-8").split(' ')
#for pdf files using pypdf2
for i in range(0, pdf.getNumPages()):
content += pdf.getPage(i).extractText() + "\n"
content = " ".join(content.replace(u"\xa0", " ").strip().split())
contents = content.encode("ascii","ignore").decode("utf-8").split(' ')
#for xml files using lxml
tree = etree.parse(path)
contents = etree.tostring(tree, encoding='utf8', method='text')
contents = contents.decode("utf-8").split(' ')
但我注意到,即使读取30个大小在50kb以下的文本文件并对其进行操作,也需要41秒。但是,如果我读取一个56mb的文本文件需要9秒钟。所以我猜是文件I/O让我的速度变慢了,而不是我的程序
你知道如何加快这个过程吗?可能将每种文件类型分解为4个不同的线程?但是,既然他们共享同一个列表,那么您将如何执行此操作,并且完成后,单个列表将写入一个文件。如果您在文件I/O上被阻止,正如您所怀疑的那样,您可能无能为力 但是,如果您的带宽很高,但延迟很糟糕,那么并行到不同的线程可能会有所帮助。尤其是在处理网络文件系统或多盘逻辑驱动器时。所以,尝试一下也无妨 但是没有理由按照文件类型来做;只需使用一个池来处理所有文件。例如,使用
futures
模块:*
import concurrent.futures
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
results = executor.map(process_file, list_of_filenames)
ThreadPoolExecutor
比基本线程池稍微聪明一点,因为它允许您构建可组合的未来,但在这里您不需要这些,所以我只是将其用作基本线程池,因为Python没有这些线程池**
创建4个线程,以及管理将任务放入这些线程并返回结果所需的所有队列和任何其他内容
然后,该方法只需遍历文件名列表中的每个文件名
,通过调用该文件名上的进程文件
创建一个任务,将其提交到池中,然后等待所有任务完成
换句话说,这与写作是一样的:
results = [process_file(filename) for filename in list_of_filenames]
…但它使用四个线程并行处理文件
如果这不够清楚,文档中有一些很好的例子
*如果您使用的是Python2.x,则需要先安装一个,然后才能使用它。或者您可以使用
多处理.dummy.Pool
,如下所述
**事实上,它确实存在于
多处理.dummy.Pool
中,但这并不是很清楚地记录在案。不太确定这是在做什么。你能解释一下吗,或者我有时间查一下。谢谢你的回复。map(…)
应该是executor.map(…)
?@moarningsun:当然可以。谢谢你抓住了!如果您有性能不佳的工作代码,您确实应该尝试使用探查器来确定代码的速度慢的地方,而不是猜测。您有喜欢使用的探查器吗?或者,除了在任何地方都坚持程序启动后的打印时间外,我该怎么做呢?即使没有分析器,您也可以非常快速地验证I/O操作是否正确:只需测试读取文件和不执行任何操作所需的时间,以及处理所需的时间。如果大致相同,那么您是对的,这肯定是I/O时间。如果速度快得多…那么,可能仍然需要I/O时间(例如,您使用的模块可能会执行大量低效的寻道或小读取),但可能不会,因此您需要分析。