Python实现多进程分词(不使用Queue队列进程通信方式)
背景:
近日公司要求编写一个基于python多进程的双语分词工具,具体要求为:1、不使用传统的进程间通信的方式,即不使用Queue队列和Pool等。2、要求文本按照进程数的大小将文件平均分成若干份,每个进程处理一部分,并将最终分词结果合并。这样的要求目的是为了提高速度:减少进程通信的时间,且可自定义开启进程的数量。
实现:
工具核心函数如下:
def find_offsets(self):
with open(self.infile, 'r', encoding='utf-8') as f:
# 文件大小
size = os.fstat(f.fileno()).st_size
# print('size=%s'%size)
chunk_size = size // self.p_num
# print('chunk_size=%s'%chunk_size)
offsets = [0 for _ in range(self.p_num + 1)]
for i in range(1, self.p_num + 1):
f.seek(chunk_size * i) # seek() 方法用于移动文件读取指针到指定位置
self.safe_readline(f)
# offsets = [0,1231,234232423,]
offsets[i] = f.tell() # tell() 方法返回文件的当前位置,即文件指针当前位置
return offsets
函数功能介绍:
find_offsets函数将输入文本作为参数,首先计算该文件的总大小size,再根据输入的进程数p_num计算每块的大小chunk_size。紧接着定义一个offsets数组,其本质是根据偏移量找到并记录文件的位置,在接下来的分词过程中使用,其返回值是一个起始为0,其余值大于0的整型数组(见代码注释)。数组的大小为进程数p_num+1。
其他函数:
def safe_readline(self, f):
pos = f.tell() # tell() 方法返回文件的当前位置,即文件指针当前位置
while True:
try:
return f.readline()
except UnicodeDecodeError:
pos -= 1
f.seek(pos) # search where this character begins
safe_readline函数用于确保划分的位置正确,这是由于考虑到中文字符占两个字节空间。如果pos来到了两个字节空间中间的位置,则我们将pos向左移一位。
# 分词并保存结果到文件
def token_and_save(self, offset=0, end=-1):
with<