在编写Python程序时,经常需要同时执行多个运算任务或多项工作以实现某些功能和使用计算机的多核提高执行效率,这里介绍一种非常简单的方法实现多进程。
multiprocessing.Pool
实现进程池这里使用的是multiprocessing
提供的Pool
方法来实现多进程
以下述代码为例:
from multiprocessing import Pool # 导入线程池
import os, time, random # 导入其他包
def long_time_task(name): # 子进程的任务
print('Run task %s (%s)...' % (name, os.getpid())) # os.getpid()为获取进程号
start = time.time() # 开始计时
time.sleep(random.random() * 10) # 等待一段时间,模拟计算耗费时间
end = time.time() # 等待完成时间戳
print('Task %s runs %0.2f seconds.' % (name, (end - start))) # 任务执行完成,输出任务执行时间
if __name__=='__main__':
print('Parent process %s.' % os.getpid())
p = Pool(4) # 创建进程池
for i in range(10):
p.apply_async(long_time_task, args=(i,)) # 向进程池中添加任务
print('Waiting for all subprocesses done...')
p.close() # 结束向进程池中添加任务(后续不能再使用apply_async方法添加新任务)
p.join() # 实现进程同步
print('All subprocesses done.')
这段代码中的long_time_task
方法是需要同时进行执行的方法。
在主函数中,首先通过p = Pool(4)
创建进程池,数字代表同时执行的子进程数量,若留空,默认为系统安装的核心数
随后,使用p.apply_async()
方法向进程池中添加任务。其中long_time_task
是将要执行的函数,而args
则指代的是函数需要传入的变量,需要注意这里要以元组
的形式传入。
若添加的任务数超出了设定的允许同时执行的最大任务数,则后续进程排队,待正在执行的子进程结束后进入执行(可以参考银行的多柜台排队,进程池设定的同时执行的子进程数量相当于银行的办理窗口,添加的进程相当于前往银行办理业务的客户,当客户数量超过了开放的窗口数,后续用户开始排队)
随后,使用p.close()
作为所有子任务添加完成的信号,在使用p.join()
命令前必须运行该命令
最后,使用p.join()
实现子进程和母进程的同步。也就是主进程执行到此处后进行确认,确认所有子进程是否已经进行完成。如果所有子进程都已经执行完成,则继续执行后续代码;若子进程仍然在进行中,则在此处等待,直到所有子进程全部执行完成再执行后续代码。(继续援引前面的例子,可以理解为银行关门前,需要等待所有客户处理完业务)
multiprocessing.Process
实现简单多进程此方法适合只需要添加一两个子进程的情况下使用,实现更为简便
from multiprocessing import Process # 导入多进程所需包
import os
import time
def run_proc(name):
print('Run child process %s (%s)...' % (name, os.getpid()))
print('child process wait 10s')
time.sleep(10) # 子进程执行任务
print('child process finished waiting')
if __name__=='__main__':
print('Parent process %s.' % os.getpid())
p = Process(target=run_proc, args=('test',)) # 添加子进程
print('Child process will start.')
p.start() # 子进程开始执行
print('parent process sleep 5s')
time.sleep(5) # 母进程执行其他任务
print('parnet process finished sleeping')
p.join() # 实现母进程与子进程的同步,确认子进程执行完后继续后续操作
print('Child process end.')
此方法与上述进程池的实现非常类似,这里不再赘述。
此外在Linux \ Unix
系统下,还可以通过os.fork()
方法实现子进程,但是由于Windows下无法使用
,且略微繁琐,故在此不述。