参考文档
说明
由于python的GIL导致在处理计算密集型任务时,会比单进程处理还要慢,最好的方法是使用多进程来进行处理,每个进程处理任务的一部分。
代码
子进程启动和退出管理
import signal
from multiprocessing import Process
import os
import time
# 启动进程数设置为4
sub_process_count = 4
# 待处理任务列表
all_task_list = [x for x in range(20)]
# 子进程的SIGTERM信号处理函数
def on_sub_process_sigterm(signo, frame):
global sub_task_id
global run_flag
# 收到SIGTERM信号后修改运行标志,子进程处理函数循环将会退出,最后子进程安全退出
run_flag = False
# 子进程的处理函数
def sub_process_func(task_id):
global sub_task_id
global run_flag
sub_task_id = task_id
run_flag = True
pid = os.getpid()
print('[{}][{}] 子进程已启动'.format(sub_task_id, pid))
for task in all_task_list[task_id::sub_process_count]: #使用python的list的切片和步长属性,确保每个进程处理任务列表中的一部分
if not run_flag:
print('[{}][{}] 子进程收到退出标志 '.format(sub_task_id, pid))
break
print('[{}][{}] 子进程正在处理任务 {} '.format(sub_task_id, pid, task))
time.sleep(10)
print('[{}][{}] 子进程安全退出'.format(sub_task_id, pid))
# 主进程的SIGTERM处理函数
def on_main_process_sigterm(signo, frame):
global sub_process_list
# 给所有子进程发送SIGTERM信号
for (task_id, p) in sub_process_list:
p.terminate()
if __name__ == '__main__':
#存储所有的子进程
global sub_process_list
sub_process_list = []
# 注册SIGTERM信号捕捉函数,来管理子进程的退出
signal.signal(signal.SIGTERM, on_main_process_sigterm)
# 启动子进程
for task_id in range(sub_process_count):
p = Process(target=sub_process_func, args=(task_id,))
p.start()
sub_process_list.append( (task_id, p) )
print('所有子进程已经启动...')
print('输入下面的命令来退出所有进程:\nkill -SIGTERM {}'.format(os.getpid()))
# 等待子进程安全退出
for (task_id, p) in sub_process_list:
p.join()
print('主进程安全退出')
import signal
from multiprocessing import Process
import os
import time
# 启动进程数设置为4
sub_process_count = 4
# 待处理任务列表
all_task_list = [x for x in range(20)]
# 子进程的SIGTERM信号处理函数
def on_sub_process_sigterm(signo, frame):
global sub_task_id
global run_flag
# 收到SIGTERM信号后修改运行标志,子进程处理函数循环将会退出,最后子进程安全退出
run_flag = False
# 子进程的处理函数
def sub_process_func(task_id):
global sub_task_id
global run_flag
sub_task_id = task_id
run_flag = True
pid = os.getpid()
print('[{}][{}] 子进程已启动'.format(sub_task_id, pid))
for task in all_task_list[task_id::sub_process_count]: #使用python的list的切片和步长属性,确保每个进程处理任务列表中的一部分
if not run_flag:
print('[{}][{}] 子进程收到退出标志 '.format(sub_task_id, pid))
break
print('[{}][{}] 子进程正在处理任务 {} '.format(sub_task_id, pid, task))
time.sleep(10)
print('[{}][{}] 子进程安全退出'.format(sub_task_id, pid))
# 主进程的SIGTERM处理函数
def on_main_process_sigterm(signo, frame):
global sub_process_list
# 给所有子进程发送SIGTERM信号
for (task_id, p) in sub_process_list:
p.terminate()
if __name__ == '__main__':
#存储所有的子进程
global sub_process_list
sub_process_list = []
# 注册SIGTERM信号捕捉函数,来管理子进程的退出
signal.signal(signal.SIGTERM, on_main_process_sigterm)
# 启动子进程
for task_id in range(sub_process_count):
p = Process(target=sub_process_func, args=(task_id,))
p.start()
sub_process_list.append( (task_id, p) )
print('所有子进程已经启动...')
print('输入下面的命令来退出所有进程:\nkill -SIGTERM {}'.format(os.getpid()))
# 等待子进程安全退出
for (task_id, p) in sub_process_list:
p.join()
print('主进程安全退出')
任务队列切片说明
sub_process_count = 4
all_task_list = [x for x in range(20)]
def sub_process_func(task_id):
task_list = []
for task in all_task_list[task_id::sub_process_count]: #
print('{}: {}'.format(task_id, task))
task_list.append(task)
return task_list
if __name__ == '__main__':
all_task_list2 = []
for task_id in range(sub_process_count):
task_list = sub_process_func(task_id)
all_task_list2 += task_list
assert len(all_task_list2) == len(all_task_list) #任务数量是一致的
assert set(all_task_list2) == set(all_task_list) #任务长度也是一致的