创建进程
multiprocessing
模块就是跨平台版本的多进程模块,提供了一个Process
类来代表一个进程对象,这个对象可以理解为是一个独立的进程,可以执行另外的事情。
示例:创建一个进程,执行两个死循环。
代码语言:javascript复制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
(进程号)。
示例:
代码语言:javascript复制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上执行,这会占用很大的空间。
如果要启动大量的子进程,可以用进程池的方式批量创建子进程:
代码语言:javascript复制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()
进程池获取任务的执行结果:
代码语言:javascript复制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()`本身就是一个阻塞方法
异步获取进程的执行结果:
代码语言:javascript复制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()
进程间不能共享全局变量
代码语言:javascript复制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))
运行结果:
代码语言:javascript复制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]