Python多进程

普通方式开启进程

from multiprocessing import Process
import os
import time

def fun(i):

    time.sleep(3)
    with open('text','r') as f:
        count = int(f.read())
        count -= 1
    with open('text','w') as f:
        f.write(str(count))
    print('这是 %s 个子进程,PID为 %s 父进程PID为 %s count:%s'%(i,os.getpid(),os.getppid(),count))



if __name__ == '__main__':
    p_s = []
    for i in range(5):
        p = Process(target=fun,args=(i,))
        p_s.append(p)

    for p in p_s:
        p.start()

继承的方式开启进程

from multiprocessing import Process
import time
class MyProcess(Process):
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)

    def run(self):
        print('开启了一个子进程...')
        self.fun()

    def fun(self):
        time.sleep(3)
        print('子进程运行了')

if __name__ == '__main__':

    p = MyProcess()
    p.start()

from multiprocessing import Process,Value,Lock
def get_num(num,lock):
    for i in range(10):
        lock.acquire()# 获取锁
        num.value -= 1
        lock.release() # 释放锁
        print(num.value)



def put_num(num,lock):
    for i in range(10):
        lock.acquire() # 获取锁
        num.value += 1
        lock.release() # 释放锁

        print(num.value)


if __name__ == '__main__':
    num = Value('i',10) # Value可以在多个进程之间共享数据
    lock = Lock() # 实例化一个锁

    get_p = Process(target=get_num,args=(num,lock))
    get_p.start()
    put_p = Process(target=put_num,args=(num,lock))
    put_p.start()
    get_p.join()
    put_p.join()
    print(num.value)

信号量

from multiprocessing import Semaphore,Process
import time
def fun(num,lock):
    lock.acquire()
    print('%s进来了。。。'%num)
    time.sleep(1)
    lock.release()
    print('%s出来了....'%num)



if __name__ == '__main__':
    lock = Semaphore(5) # 相当于实例化了一个锁,但是锁有五把钥匙
    for i in range(50):
        p = Process(target=fun,args=(i,lock))
        p.start()
from multiprocessing import Event,Process
import time


def signal_lamp(e):
    while True:
        if e.is_set(): # 如果当前事件状态为true那么将,状态改为false阻塞进程,模拟实现红灯亮起状态
            print('红灯凉了..')
            e.clear()# 将event状态改为false
        else:# 如果当前事件状态为false那么将,状态改为true允许进程运行,模拟实现绿灯灯亮起状态
            print('绿灯凉了....')
            e.set()#将event状态改为true
        time.sleep(10)


def Car(i,e):
    e.wait() # 如果e.is_set()为false则阻塞在这一步,否则运行
    print('第%s辆车过去了....'%i)

if __name__ == '__main__':
    # Event几种方法:
    
    # event.isSet():返回event的状态值;
    
    # event.wait():
    # 如果
    # event.isSet() == False将阻塞进程;
    # event.isSet() == True 进程正常运行;
    
    # event.set(): 设置event的状态值为True,所有阻塞池的进程激活进入就绪状态, 等待操作系统调度;
    
    # event.clear():恢复event的状态值为False。
    e = Event()
    sl = Process(target=signal_lamp,args=(e,))
    sl.start()

    for i in range(10):
        p = Process(target=Car,args=(i,e,))
        p.start()

生产者消费者模型Queue

from multiprocessing import Queue,Process

def producer(q):
    for i in range(20):
        q.put('第 %s 个包子' % (i,))


def comsumer(q):
    while True:
        info = q.get()
        if not info:
            break
        print('消费:%s'%(info,))


if __name__ == '__main__':
    q = Queue(20) # 创建一个队列,队列内部实现了锁机制,所以在进程中共享数据是安全的
    p_p = Process(target=producer,args=(q,))
    p_c = Process(target=comsumer,args=(q,))

    p_p.start()
    p_c.start()
    p_p.join() # 等待生产者完成
    q.put(None)# 如果生产者完成了生成,则在队列中存入None如果,消费者读取到None则退出

生产者消费者模型JoinableQueue

from multiprocessing import Process,JoinableQueue

def producer(q):
    for i in range(20):
        q.put('第 %s 个包子' % (i,))
    q.join() # 阻塞,一直阻塞到消费者消费完所有包子(队列中记录了生产的包子个数)

def comsumer(q):
    while True:
        info = q.get()
        print('消费:%s'%(info,))
        q.task_done()# 每消费完一个包子,就会发送一个信号到队列。
        




if __name__ == '__main__':
    q = JoinableQueue(20)

    p_p = Process(target=producer,args=(q,))
    p_c = Process(target=comsumer,args=(q,))

    p_p.start()
    p_c.daemon = True # 将消费者进程设置为守护进程,那么当主进程的代码全部执行完毕,则会退出消费者进程
    p_c.start()
    p_p.join()  # 主进程等待生产者进程完成
    '''
    这段代码的中心思想:
    首先:生产者进程q.join()会等待消费者吃完所有包子之后才会结束
    然后:主进程 p_p.join() 会等待生产者进程结束
    最后:p_c.daemon = True 会等待主进程结束,然后结束
    
    导致的结果:消费者吃完所有包子 -> 生产者进程结束 -> 主进程代码执行完毕 -> 消费者进程(守护进程)结束
    
    '''

管道

from multiprocessing import Process,Pipe

def producer(con):
    con1,con2 = con
    con2.close()
    for i in range(20):
        con1.send('第 %s 个包子' % (i,))


def comsumer(con):
    con1, con2 = con
    con1.close()
    while True:
        try:
            info = con2.recv()
        except EOFError:
            con2.close()
            break

        print('消费:%s'%(info,))

if __name__ == '__main__':
    # 管道内部没有实现锁机制,需要自己实现。所以管道在多进程中共享数据是不安全的
    con1,con2 = Pipe() # 管道的核心,如果是con1发送,那么只能用con2接收
    p_p = Process(target=producer,args=((con1,con2),))

    p_c = Process(target=comsumer,args=((con1,con2),))
    p_p.start()
    p_c.start()
    p_p.join()
    con1.close()

进程池

from multiprocessing import Pool
import os
import time
def fun(num):

    return num + 1

def call_back(num):
    with open('a.txt','a') as f:
        f.write(str(num))
if __name__ == '__main__':
    pool = Pool(os.cpu_count()+1) # os.cpu_count() 可以计算出当前计算机的核数
    # # map方法 用时:0.2000112533569336
    # start = time.time()
    # res = pool.map(fun,range(100)) # pool.map(函数,可迭代对象) 将可迭代对象中的每一个元素传入函数计算,并且将计算结果返回 res得到一个列表
    # pool.close()  # 想要主进程等待进程池中的任务全部完成。首先得关闭进程池,使新任务无法在放入进程池。之后在使用pool.join()来使主进程阻塞等待
    # pool.join()
    # print(res)
    # print(time.time()-start)


    # #apply(同步)方法,跟没开多进程一样,一个一个执行 用时 0.15600895881652832
    # start = time.time()
    # for i in range(100):
    #     res = pool.apply(func=fun,args=(i,)) # pool.apply(func=函数,args=(参数,)) 可以得到函数的返回值
    #     print(res)
    # print(time.time()-start)

    # apply(异步)方法 用时 0.08100461959838867
    # pool.apply(func=函数,args=(参数,),callback=回调函数)
        #   使用 res.get()可以得到函数的返回值。
        #   回调函数接收一个参数,参数就是func的返回值,自动传参。(回调函数由主进程调用)
    
    # #回调函数的练习 
    # start = time.time()
    # res_l = []
    # for i in range(100):
    #     res = pool.apply_async(func=fun,args=(i,),callback=call_back)
    #     res_l.append(res)
    # pool.close()
    # pool.join()
    # print(time.time()-start)

 

posted on 2019-07-16 16:16  信奉上帝的小和尚  阅读(157)  评论(0编辑  收藏  举报

导航