Ray*_* P. 3 python multiprocessing
我有一个小的python程序,它逐行浏览一个大文本文件(5Mil +行),如果满足条件,则从每行中提取单个单词,然后将该单词附加到列表中(如果它尚未存在).之后我有一个巨大的列表,我需要按字母顺序排序,然后将列表中的项目写入新的文本文件.
代码如下所示:
big_list = []
with open('big_text_file.txt', 'r', encoding='UTF8') as f:
for line in f:
# some validation specific to line structure:
if line[0] not in (1, 2, 3, 4, 5, 6, 7, 8, 9, 0) and '\t' in line:
word = line.rsplit('\t')[0].lower()
if word not in big_list:
big_list.append(word)
sorted_list = sorted(big_list)
with open('results_file.txt', 'w', encoding='UTF8') as r:
for item in sorted_list:
r.write(item + "\n")
Run Code Online (Sandbox Code Playgroud)
问题是它很慢.有500万行,现在已经运行了12个多小时(!),还远未完成.我一定做错了什么.我有一个8核CPU,但在这种情况下只使用一个.CPU负载仅为12%.我可以应用多处理来加快速度吗?或者由于此代码的简单性,它没有多大用处?我仍然需要针对一个列表验证所有单词.
任何建议将不胜感激.
正如评论中提到的,这里的主要瓶颈是使用a list.
旁白:if line[0] not in (1, 2, 3, 4, 5, 6, 7, 8, 9, 0)很慢,不起作用:line[0]是一个字符,而不是整数.使用isdigit()了点.
声明big_list为set(),您可以替换:
if word not in big_list:
big_list.append(word)
Run Code Online (Sandbox Code Playgroud)
只是
big_list.add(word)
Run Code Online (Sandbox Code Playgroud)
(word仅在尚未添加时才会添加set,并且与O(n)a 相比检查非常快,list因为它使用散列)
更好:您可以在一行中使用集合理解来重写代码(第一部分,甚至是排序部分):
with open('big_text_file.txt', 'r', encoding='UTF8') as f:
big_list = sorted({line[:line.find('\t')].lower() for line in f if not line[0].isdigit() and '\t' in line})
Run Code Online (Sandbox Code Playgroud)
注意更好的方法来获取行的第一部分,避免分裂(并生成一个你几乎不使用的列表)
正如上面所说的,不需要测试in了set:如果这个词已经在它,它不会被再次插入,并插入决定试验的目的是要快.
请注意,多处理可能有所帮助,但是你会遇到磁盘I/O瓶颈并且算法会更复杂,因为你必须通过跳过8个相等的行号来"拆分"你的大文件,创建集合并交叉它们......让我们坚持单一处理部分,看看它是如何发展的.