『Python』多进程处理
尝试学习python的多进程模组,对比多线程,大概的区别在:
1.多进程的处理速度更快
2.多进程的各个子进程之间交换数据很不方便
多进程调用方式
进程基本使用multicore()
进程池优化进程的调用multicore_pool(),在使用进程池的时候,运许函数有return,而基本用法中进程是接收不了return的
进程队列用法,大部分方法和python的基本队列是一致的,
q=mp.Queue() 声明
q.put() 添加
q.get() 释放
q.empty() 判断是不是空的
""" Created on Tue Dec 5 09:00:00 2017 @author: hellcat """ import time import numpy as np import threading as td import multiprocessing as mp def job(q): for i in range(3): q.put(i) def multicore(): q=mp.Queue() ps = [mp.Process(target=job,args=(q,)), mp.Process(target=job,args=(q,))] # 基本的子进程创建方法 for p in ps: p.start() time.sleep(3) for p in ps: p.join() # 需要协调结束 while True: if q.empty() != True: print(q.get()) else: break def multithread(): q=mp.Queue() ps = [td.Thread(target=job,args=(q,)), td.Thread(target=job,args=(q,))] # 基本的子线程创建方法 for p in ps: p.start() time.sleep(3) for p in ps: p.join() while True: if q.empty() != True: print(q.get()) else: break def job_pool(q): res0 = 0 for i in range(np.random.randint(10)): res0 += i**3 return res0 def multicore_pool(): pool = mp.Pool(processes=2) # 初始化进程池,可以指定进程数 res1 = pool.map(job_pool,range(20)) # map方法在线程池中同时添加多个线程 print(res1) # 返回值为函数的return res2 = [pool.apply_async(job_pool,(i,)) for i in range(20)] # 在进程池中单个添加进程 print([res.get() for res in res2]) # 注意此时每个进程的返回并不直接是return,需要get方法得到的才是return # for res in res2: # print(res.get()) if __name__=='__main__': # multicore() # multithread() multicore_pool()
进程共享变量 & 进程锁
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Created on Tue Dec 5 10:15:58 2017 @author: hellcat """ import time import multiprocessing as mp def job(v,num,l): # 需要把共享变量实例作为参数传入才行 l.acquire() # 进程锁锁住 for _ in range(10): time.sleep(0.1) v.value += num # 获取共享变量的值,并进行操作 print(v.value) l.release() # 进程锁释放 def muticore(): l = mp.Lock() # 实例化进程锁 v = mp.Value('i',0) # 实例化共享变量 # p = mp.Pool(processes=2) # p.map(job,((v,1,l),(v,3,l))) p1 = mp.Process(target=job,args=(v,1,l)) p2 = mp.Process(target=job,args=(v,3,l)) p1.start() p2.start() p1.join() p2.join() if __name__=='__main__': muticore()
不同于多线程使用全局变量就可以以共享变量,多进程必须使用 v = mp.Value('i',0)这样的语句声明变量(其实还可以是mp.Array('i',[1,2,3]),注意,这里只能是1维的list,[[1,2]]这样都是不可以的),并将v作为参数传给函数,在函数内部使用的时候也需要使用v.value来唤醒其值。
进程锁会在锁住时阻止其他进程使用共享变量,所以可以看到输出中先执行了10次+1,然后执行了10次+3,而不使用进程锁+1和+3会无规律的交替进行:
注释掉进程锁:
1
4
5
8
9
12
13
16
17
20
21
24
25
28
29
32
33
36
37
40使用进程锁(上面代码没有注释掉进程锁):
1
2
3
4
5
6
7
8
9
10
13
16
19
22
25
28
31
34
37
40