使用Python多线程读取txt文件
我想用Python读取一个文件(逐行扫描并查找特定词汇),然后把结果写出来,比如每个词汇的计数。我需要对很多文件(超过3000个)进行这个操作。请问可以用多线程来实现吗?如果可以的话,怎么做呢?
具体情况是这样的:
- 读取每个文件并扫描它的每一行
- 把计数结果写到同一个输出文件中,包含我读取的所有文件的结果。
第二个问题是,这样做能提高读写的速度吗?
希望这样说清楚了。谢谢,
Ron。
2 个回答
1
是的,这个可以通过并行的方式来实现。
不过,在Python中,用多个线程来实现并行处理比较困难。因此,multiprocessing
模块是进行并行处理的更好选择。
至于你能期待达到什么样的速度提升,这很难说。因为这取决于有多少工作可以并行处理(越多越好),以及有多少工作必须串行处理(越少越好)。
23
我同意 @aix 的看法,使用 multiprocessing
确实是个好主意。不管你遇到的是什么情况,输入输出的速度总是有限的——无论你同时运行多少个进程,读取速度都是有上限的。不过,还是有可能会有一些速度上的提升。
想象一下,下面这个例子(input/ 是一个包含多个 .txt 文件的文件夹,文件来自古腾堡计划)。
import os.path
from multiprocessing import Pool
import sys
import time
def process_file(name):
''' Process one file: count number of lines and words '''
linecount=0
wordcount=0
with open(name, 'r') as inp:
for line in inp:
linecount+=1
wordcount+=len(line.split(' '))
return name, linecount, wordcount
def process_files_parallel(arg, dirname, names):
''' Process each file in parallel via Poll.map() '''
pool=Pool()
results=pool.map(process_file, [os.path.join(dirname, name) for name in names])
def process_files(arg, dirname, names):
''' Process each file in via map() '''
results=map(process_file, [os.path.join(dirname, name) for name in names])
if __name__ == '__main__':
start=time.time()
os.path.walk('input/', process_files, None)
print "process_files()", time.time()-start
start=time.time()
os.path.walk('input/', process_files_parallel, None)
print "process_files_parallel()", time.time()-start
当我在我的双核电脑上运行这个时,速度明显变快了(虽然没有达到两倍快):
$ python process_files.py
process_files() 1.71218085289
process_files_parallel() 1.28905105591
如果文件小到可以放进内存,而且你有很多处理任务不是受输入输出限制的,那么你应该能看到更大的提升。