多进程
同步和异步
同步是指:当程序1调用程序2时,程序1停下不动,直到程序2完成回到程序1来,程序1才继续执行下去。  
异步是指:当程序1调用程序2时,程序1径自继续自己的下一个动作,不受程序2的的影响。
同步是指:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式。  
异步是指:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。
创建子进程
from multiprocessing import Process import time import os def func(arg1, arg2): print('*'*arg1) time.sleep(2) print('子进程:', os.getpid()) print('*'*arg2) if __name__ == '__main__': # windows系统中必须有这一行 p = Process(target=func, args=(10, 20)) # 注册,args是传递参数的方式 # p.daemon = True # 设置子进程为守护进程,父进程结束后子进程自动结束 p.start() # 通知操作系统开启一个子进程 print('########') p.join() # 感知一个子进程的结束,将一个异步程序改为同步,join后的内容在p结束后才执行 print('父进程:', os.getpid()) print('父进程的父进程:', os.getppid()) print('运行完了')
创建多进程
方法一
from multiprocessing import Process import time def func(arg): print('进程%s开始' % arg) time.sleep(1) print('进程%s结束' % arg) if __name__ == '__main__': p_list = [] for i in range(5): p = Process(target=func, args=(i,)) p.start() p_list.append(p) for p in p_list: # 所有子进程结束后再执行后面的父进程 p.join() print('主进程结束')
方法二
import os from multiprocessing import Process class MyProcess(Process): def __init__(self, arg1, arg2): # 传递参数的方式 super().__init__() self.arg1 = arg1 self.arg2 = arg2 def run(self): # 方法名必须为run print(os.getpid()) print(self.arg1) print(self.arg2) if __name__ == '__main__': print('主进程:', os.getpid()) p1 = MyProcess(1, 2) p1.start() p2 = MyProcess(3, 4) p2.start()
守护进程
from multiprocessing import Process import time # 守护进程会等主进程的代码执行完之后自动结束,(代码执行完即可,不一定等到主进程结束) def func(): while True: time.sleep(0.5) print('子进程') if __name__ == '__main__': p = Process(target=func) p.daemon = True # 在p.start()之前,设置子进程为守护进程 p.start() # print(p.name, p.pid) # 进程名和进程id # print(p.is_alive()) # 检验进程是否还活着 # p.terminate() # 结束子进程 i = 0 while i < 5: print('主进程执行中') time.sleep(1) i += 1
进程锁
# 文件db的内容为:{"count":5} # 注意一定要用双引号,不然json无法识别 # 并发运行,效率高,但竞争写同一文件,数据写入错乱 from multiprocessing import Process, Lock import time,json,random def search(): dic = json.load(open('db')) print('\033[34m剩余票数%s\033[0m' % dic['count']) def get(arg): dic = json.load(open('db')) time.sleep(0.2) # 模拟读数据的网络延迟 if dic['count'] > 0: dic['count'] -= 1 time.sleep(0.2) # 模拟写数据的网络延迟 json.dump(dic, open('db', 'w')) print('进程%s' % arg + '\033[32m购票成功\033[0m') else: print('进程%s' % arg + '\033[31m购票失败\033[0m') def task(lock, arg): search() lock.acquire() # 拿钥匙 get(arg) lock.release() # 还钥匙 if __name__ == '__main__': lock = Lock() for i in range(10): # 模拟并发10个客户端抢票 p = Process(target=task, args=(lock, i)) p.start()
信号量
from multiprocessing import Process, Semaphore import time def func(i, sem): sem.acquire() # 拿钥匙 print('进程%s开始执行' % i) time.sleep(5) print('进程%s执行结束' % i) sem.release() # 还钥匙 if __name__ == '__main__': sem = Semaphore(4) # 设置4把钥匙 for i in range(20): p = Process(target=func, args=(i, sem)) p.start()
事件
from multiprocessing import Event e = Event() # 创建了一个事件,默认状态是False print(e.is_set()) # 查看事件状态 e.set() # 将事件状态改为True print(e.is_set()) e.wait() # 根据事件状态决定是否阻塞,True不阻塞,False阻塞,不wait不阻塞。 print('*'*10) e.clear() # 将事件状态改为False print(e.is_set()) e.wait() # 等待时间状态改为True print('*'*10)
红绿灯实现
from multiprocessing import Event, Process import time import random def cars(e, i): if not e.is_set(): print('car%s等待中' % i) e.wait() # 阻塞,等待时间状态变为True print('car%s通过' % i) def light(e): while True: if e.is_set(): e.clear() print('\033[31m红灯\033[0m') else: e.set() print('\033[32m绿灯\033[0m') time.sleep(1) if __name__ == '__main__': e = Event() traffic = Process(target=light, args=(e,)) traffic.start() for i in range(20): car = Process(target=cars, args=(e, i)) car.start() time.sleep(random.random())
进程池
简单实现
import os import time from multiprocessing import Pool def func(n): print("start func%s" % n, os.getpid()) time.sleep(1) print("end func%s" % n, os.getpid()) if __name__ == '__main__': p = Pool(5) for i in range(10): # p.apply(func, args=(i,)) # 同步执行 p.apply_async(func, args=(i,)) # 异步执行 p.close() # 结束进程池接受任务 p.join() # 感知进程池中的任务执行结束
有返回值的进程池函数
import time from multiprocessing import Pool # 有返回值的进程池函数 def func(i): time.sleep(0.5) return i*i if __name__ == '__main__': p = Pool(5) res_l = [] for i in range(10): res = p.apply_async(func, args=(i,)) res_l.append(res) for res in res_l: print(res.get()) # get方法获取res的返回值,不能放在上一个for里面,否则会改异步为同步
进程池回调函数
import os from multiprocessing import Pool def func1(n): print('func1:', os.getpid()) return n*n def func2(n): print('func2:', os.getpid()) # 回调函数在主进程中执行 print(n) if __name__ == '__main__': print('主进程:', os.getpid()) p = Pool(5) p.apply_async(func1, args=(10,), callback=func2) # func1的返回值作为参数传给回调函数 p.close() p.join()
进程间通信
python提供了多种进程通信的方式,主要Queue和Pipe这两种方式,Queue用于多个进程间实现通信,Pipe是两个进程的通信
Queue有两个方法:
- 
Put方法:以插入数据到队列中,他还有两个可选参数:blocked和timeout 
- 
Get方法:从队列读取并且删除一个元素。同样,他还有两个可选参数:blocked和timeout 
from multiprocessing import Process, Queue import os,time,random # 写数据进程执行的代码 def proc_write(q, urls): print('Process is write....') for url in urls: q.put(url) print('put %s to queue... ' % url) time.sleep(random.random()) # 读数据进程的代码 def proc_read(q): print('Process is reading...') while True: url = q.get(True) print('Get %s from queue' %url) if __name__ == '__main__': # 父进程创建Queue,并传给各个子进程 q = Queue() proc_write1 = Process(target=proc_write, args=(q, ['url_1', 'url_2', 'url_3'])) proc_write2 = Process(target=proc_write, args=(q, ['url_4', 'url_5', 'url_6'])) proc_reader = Process(target=proc_read, args=(q,)) # 启动子进程,写入 proc_write1.start() proc_write2.start() proc_reader.start() # 等待proc_write1结束 proc_write1.join() proc_write2.join() # proc_reader进程是死循环,强制结束 proc_reader.terminate()
Pipe通信机制,
Pipe常用于两个进程,两个进程分别位于管道的两端
Pipe方法返回(conn1,conn2)代表一个管道的两个端,Pipe方法有duplex参数,默认为True,即全双工模式,若为FALSE,conn1只负责接收信息,conn2负责发送,
send和recv方法分别为发送和接收信息
import multiprocessing import os,time,random #写数据进程执行的代码 def proc_send(pipe,urls): #print 'Process is write....' for url in urls: print 'Process is send :%s' %url pipe.send(url) time.sleep(random.random()) #读数据进程的代码 def proc_recv(pipe): while True: print('Process rev:%s' %pipe.recv()) time.sleep(random.random()) if __name__ == '__main__': #父进程创建pipe,并传给各个子进程 pipe = multiprocessing.Pipe() p1 = multiprocessing.Process(target=proc_send,args=(pipe[0],['url_'+str(i) for i in range(10) ])) p2 = multiprocessing.Process(target=proc_recv,args=(pipe[1],)) #启动子进程,写入 p1.start() p2.start() p1.join() p2.terminate()

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号