创建进程
multiprocessing
模块就是跨平台版本的多进程模块,提供了一个Process
类来代表一个进程对象,这个对象可以理解为是一个独立的进程,可以执行另外的事情。
示例:创建一个进程,执行两个死循环。
from multiprocessing import Process import time def run_proc(): """子进程要执行的代码""" while True: print("----2----") time.sleep(1) if __name__=='__main__': p = Process(target=run_proc) p.start() while True: print("----1----") time.sleep(1)
说明
创建子进程时,只需要传入一个执行函数和函数的参数,创建一个Process
实例,用start()
方法启动。
方法说明
Process(target [, name [, args [, kwargs]]])
target
:如果传递了函数的引用,可以任务这个子进程就执行这里的代码。args
:给target
指定的函数传递的参数,以元组的方式传递。kwargs
:给target
指定的函数传递命名参数。name
:给进程设定一个名字,可以不设定。
Process
创建的实例对象的常用方法:
start()
:启动子进程实例(创建子进程)。is_alive()
:判断进程子进程是否还在活着。join([timeout])
:是否等待子进程执行结束,或等待多少秒。terminate()
:不管任务是否完成,立即终止子进程。
Process
创建的实例对象的常用属性:
name
:当前进程的别名,默认为Process-N
,N
为从1开始递增的整数。pid
:当前进程的pid
(进程号)。
示例:
from multiprocessing import Process import os from time import sleep def run_proc(name, age, **kwargs): for i in range(10): print('子进程运行中,name= %s,age=%d ,pid=%d...' % (name, age, os.getpid())) print(kwargs) sleep(0.2) if __name__=='__main__': p = Process(target=run_proc, args=('test',18), kwargs={"m":20}) p.start() sleep(1) # 1秒中之后,立即结束子进程 p.terminate() p.join()
Pool
开启过多的进程并不能提高你的效率,反而会降低你的效率,假设有500个任务,同时开启500个进程,这500个进程除了不能一起执行之外(CPU没有那么多核),操作系统调度这500个进程,让他们平均在4个或8个CPU上执行,这会占用很大的空间。
如果要启动大量的子进程,可以用进程池的方式批量创建子进程:
def task(n): print('{}----->start'.format(n)) time.sleep(1) print('{}------>end'.format(n)) if __name__ == '__main__': p = Pool(8) # 创建进程池,并指定进程池的个数,默认是CPU的核数 for i in range(1, 11): # p.apply(task, args=(i,)) # 同步执行任务,一个一个地执行任务,没有并发效果 p.apply_async(task, args=(i,)) # 异步执行任务,可以达到并发效果 p.close() p.join()
进程池获取任务的执行结果:
def task(n): print('{}----->start'.format(n)) time.sleep(1) print('{}------>end'.format(n)) return n ** 2 if __name__ == '__main__': p = Pool(4) for i in range(1, 11): res = p.apply_async(task, args=(i,)) # `res` 是任务的执行结果 print(res.get()) # 直接获取结果的弊端是,多任务又变成同步的了 p.close() # p.join() 不需要再`join`了,因为 `res.get()`本身就是一个阻塞方法
异步获取进程的执行结果:
import time from multiprocessing.pool import Pool def task(n): print('{}----->start'.format(n)) time.sleep(1) print('{}------>end'.format(n)) return n ** 2 if __name__ == '__main__': p = Pool(4) res_list = [] for i in range(1, 11): res = p.apply_async(task, args=(i,)) res_list.append(res) # 使用列表来保存进程执行结果 for re in res_list: print(re.get()) p.close()
进程间不能共享全局变量
from multiprocessing import Process import os nums = [11, 22] def work1(): """子进程要执行的代码""" print("in process1 pid=%d ,nums=%s" % (os.getpid(), nums)) for i in range(3): nums.append(i) print("in process1 pid=%d ,nums=%s" % (os.getpid(), nums)) def work2(): """子进程要执行的代码""" nums.pop() print("in process2 pid=%d ,nums=%s" % (os.getpid(), nums)) if __name__ == '__main__': p1 = Process(target=work1) p1.start() p1.join() p2 = Process(target=work2) p2.start() print('in process0 pid={} ,nums={}'.format(os.getpid(),nums))
运行结果:
in process1 pid=2707 ,nums=[11, 22] in process1 pid=2707 ,nums=[11, 22, 0] in process1 pid=2707 ,nums=[11, 22, 0, 1] in process1 pid=2707 ,nums=[11, 22, 0, 1, 2] in process0 pid=2706 ,nums=[11, 22] in process2 pid=2708 ,nums=[11]