|
|
|
|
'''
|
|
|
|
|
使用 multiprocessing.Manager:
|
|
|
|
|
Manager 提供了一个可以在不同进程之间共享和修改的数据类型,如 list, dict, Namespace 等。
|
|
|
|
|
它实际上是在背后启动了一个单独的服务器进程,其他进程通过代理来访问这些共享对象。
|
|
|
|
|
|
|
|
|
|
使用 multiprocessing.Manager 来完成统计词频
|
|
|
|
|
需要注意:
|
|
|
|
|
- Manager() 必须用函数包起来,不能按脚本随便放外面,否则会提示freeze_support
|
|
|
|
|
- 工作函数需要放到外面,不能做内部函数。否则会提示参数错误
|
|
|
|
|
- 无法在 Jupyter 类似环境运行
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
from cppy.cp_util import *
|
|
|
|
|
from collections import Counter
|
|
|
|
|
from multiprocessing import Manager, Process
|
|
|
|
|
|
|
|
|
|
stop_words = get_stopwords()
|
|
|
|
|
|
|
|
|
|
def process_chunk(shared_chunks,word_count):
|
|
|
|
|
while True:
|
|
|
|
|
try:
|
|
|
|
|
chunk = shared_chunks.pop(0) # 从共享列表中取出一个数据块
|
|
|
|
|
if chunk is None: break # 如果取出的是None,表示所有数据块已处理完毕
|
|
|
|
|
words = extract_str_words(chunk)
|
|
|
|
|
for word in words:
|
|
|
|
|
if word not in stop_words:
|
|
|
|
|
word_count[word] = word_count.get(word, 0) + 1
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(e)
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
@timing_decorator
|
|
|
|
|
def main():
|
|
|
|
|
# 创建一个Manager实例
|
|
|
|
|
manager = Manager()
|
|
|
|
|
shared_chunks = manager.list()
|
|
|
|
|
word_count = manager.dict()
|
|
|
|
|
|
|
|
|
|
# 读取文件并按块大小分割,将块添加到共享列表中
|
|
|
|
|
chunk_size = 1024 * 10 # 假设每个块是10KB,可以根据需要调整
|
|
|
|
|
with open(testfilepath, 'r', encoding='utf-8') as f:
|
|
|
|
|
while True:
|
|
|
|
|
chunk = f.read(chunk_size)
|
|
|
|
|
if not chunk: break
|
|
|
|
|
shared_chunks.append(chunk)
|
|
|
|
|
shared_chunks.append(None)
|
|
|
|
|
print('-------------------',len(shared_chunks))
|
|
|
|
|
processes = [ Process( target=process_chunk,
|
|
|
|
|
args=(shared_chunks,word_count))
|
|
|
|
|
for _ in range( 4 ) ] # 假设启动4个工作进程
|
|
|
|
|
for p in processes: p.start()
|
|
|
|
|
for p in processes: p.join()
|
|
|
|
|
|
|
|
|
|
# 将Manager类型的字典转换为普通的字典,以便使用Counter
|
|
|
|
|
word_count = dict(word_count)
|
|
|
|
|
word_freqs = Counter(word_count).most_common(10)
|
|
|
|
|
print_word_freqs(word_freqs)
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
main()
|