我有一个小的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")
问题是它很慢。有500万行,现在已经运行了12个多小时(!),还远未完成。我一定做错了什么。我有一个8核CPU,但在这种情况下只使用一个。 CPU负载仅为12%。我可以应用多处理来加快速度吗?或者由于此代码的简单性,它没有多大用处?我仍然需要针对一个列表验证所有单词。
非常感谢任何建议。
答案 0 :(得分:5)
正如评论中提到的,这里的主要瓶颈是使用list
。
除此之外:if line[0] not in (1, 2, 3, 4, 5, 6, 7, 8, 9, 0)
速度慢且不起作用:line[0]
是 char ,而不是整数。请使用isdigit()
。
将big_list
声明为set()
,您可以替换:
if word not in big_list:
big_list.append(word)
只是
big_list.add(word)
(仅当word
中尚未添加set
时才会添加,O(n)
与list
相比检查速度非常快,因为它使用哈希值{} p>
更好:你可以在一行中使用集合理解来重写代码(第一部分,甚至是排序部分):
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})
注意更好的方法来获取行的第一部分,避免分裂(并生成一个你几乎不使用的列表)
如上所述,无需为in
测试set
:如果该单词已经在其中,则不会再次插入,并且插入决策的测试设计为快速
请注意,多处理可以帮助,但是你会遇到磁盘I / O瓶颈并且算法会更复杂,因为你必须通过跳过8个相等的部分来“拆分”你的大文件行号,创建集合,并交叉它们......让我们坚持单一处理部分,看看它是如何发展的。