我正试图在python中处理多线程。我有工作代码来计算单词数,带有文本的行数,并创建一个带有每个单词计数的字典。它可以在代码注释中提到的小文件上快速运行。但是我通常使用glob来拉入多个文件。当我这样做时,我的运行时间显着增加。同时,由于我的脚本是单线程的,我看到我有3个其他核心闲置而一个最大化。
我以为我会给pythons多线程模块一个镜头,这是我到目前为止所做的(非工作):
#!/bin/python
#
# test file: http://www.gutenberg.org/ebooks/2852.txt.utf-8
import fileinput
from collections import defaultdict
import threading
import time
inputfilename = 'pg2852.txt'
exitFlag = 0
line = []
line_counter = 0
tot_words = 0
word_dict = defaultdict(int)
def myCounters( threadName, delay):
for line in fileinput.input([inputfilename]):
line = line.strip();
if not line: continue
words = line.split()
tot_words += len(words)
line_counter += 1
for word in words:
word_dict[word] += 1
print "%s: %s:" %( threadName, time.ctime(time.time()) )
print word_dict
print "Total Words: ", tot_words
print "Total Lines: ", line_counter
try:
thread.start_new_thread( myCounters, ("Thread-1", 2, ) )
thread.start_new_thread( myCounters, ("Thread-2", 4, ) )
except:
print "Error: Thread Not Started"
while 1:
pass
对于那些尝试此代码的人来说,它不起作用。我假设我需要将输入文件分成块并以某种方式合并输出。 ? map / reduce?也许有一个更简单的解决方案?
编辑:
可能是这样的:
答案 0 :(得分:5)
首先,你是正确的,你需要使用并行进程而不是并行线程。由于Global Interpreter Lock(GIL),执行此类任务 [参见下面的ETA]将无法很好地扩展到python下的多个线程。
如果要并行处理单个文件,显而易见的方法是首先检查文件大小,然后将相等大小的块分配给多个进程。这只会涉及告诉每个进程从文件中的哪个位置开始,以及结束的位置。 (当然,你必须要小心不要计算任何单词或行两次。一个简单的方法是让每个进程忽略初始字节,直到它到达行的开头,然后开始计数)。
但是,您在问题中说明您将使用glob来处理多个文件。因此,不是采用复杂的分块文件路径并将块分配给不同的进程,更简单的选择就是将不同的文件分配给不同的进程。
<强> ETA:强>
在Python中使用线程适用于某些用例,例如使用长时间阻塞的I / O函数。 @uselpa是正确的,如果处理是I / O绑定,那么线程可能表现良好,但这不是这里的情况,因为瓶颈实际上是解析,而不是文件I / O.这是由于Python作为解释语言的性能特征;在编译语言中,I / O更可能成为瓶颈。
我提出这些说法是因为我刚刚根据原始代码进行了一些测量(使用包含100个pg2852.txt连接副本的测试文件):