python多进程笔记2

来源:互联网 发布:网络职业推手公司 编辑:程序博客网 时间:2024/05/20 07:53
2017/11/4 进程间通信,进程池
进程间通信(IPC,inter-process communication):生产进程生产食物,消费进程购买食物,消费进程一直监视生产状况,只要一有食物就将其取出来,如果取到食物None,两者关系结束,于是主进程也结束。
远程过程调用协议(remote procedure call protocal),需要某些传输协议
一般情况下 父进程会等子进程结束再结束


=====================================================================
1.进程间通信常用方式:
进程间传递数据
(1)队列:
from multiprocessing import Queue(multiprocessing.Queue)
(前一章:from queue import PriorityQueue


A.from multiprocessing import Queue(multiprocessing.Queue):
在多线程中传递数据,交换数据,进行通信;
它与一般的数据结构中的队列的差别为更加符合多进程的特性:序列化和反序列化;
对数据做了一些通信商的加工,保证多进程的安全性;
在这里使用多进程的数据通信,不需要考虑多进程可能带来的安全隐患,直接使用;
multiprocessing.Queue在进程间通信是python比价提倡的一种方式


B.from queue import PriorityQueue(queue.PriorityQueue):
存储数据的一种数据结构


(2)管道:
管道中,子进程间只能单向通信,一个子进程在定义管道后只能get或者put;
conn1只能接消息,conn2只能发送消息,不用的一端close(原因在于单缓存),如果要实现双向通信,就设置两根管道
但是队列中子进程既可以get也可以put;
匿名管道:只能在父子进程中使用
命名管道:没有沁园关系的进程之间也可以通信


(3)文件:
open,read,write,seek,tell,close
mode:r,w,a,b
with open('test.txt') as f:  #该操作方式可以自行关闭文件 不必f.close()
早期时各种硬件设备都是私有接口,unix系统将设备文件化,用r,w,a,b等api接口对设备进行操作
(4)共享内存
-------------------------------
进程间传递信号
(5)信号量
(6)事件
(7)互斥量
from multiprocessing import Lock
lock.acquire() 
money.value += 1      #注意锁的粒度,尽快最小话,开销最小;粒度最小原则
lock.release()
--------------------------------
(8)Socket




=====================================================================
作业:
(1)队列实现生产者消费者模型;生产者生产[0,1,2,3,4,5,6,7,8,9,10]
消费者能够在处理完list序列后退出
(2)使用互斥锁去完成银行存取款操作,存款10000,A取10次,每次取100;B存5次,每次存200
(3)面向对象方法实现第一个作业的第二题myTimer


(1)
from multiprocessing import Queue
from multiprocessing import Process
import time


def consumer(input_q): 
     while True:
         item = input_q.get()
         if item == None:               
             break
         print(item)


def producer(sequence,output_p):
     for i in sequence:
         time.sleep(1)
         output_p.put(i)


if __name__ == '__main__':
     q= Queue()
     con_p = Process(target=consumer,args=(q,))  
     con_p.start()
     sequence =[1,2,3,4,5,6,7,8,9,10]
     producer(sequence,q)  
     q.put(None) 


(2)
from multiprocessing import Process
from multiprocessing import Value   #在不同的进程间共享的变量
from multiprocessing import Lock
import time


def deposit(money,lock):    #存钱
    for i in range(5):
        time.sleep(0.001)
        lock.acquire()   #上锁的操作
        money.value += 200
        lock.release()


def withdraw(money,lock):   #取钱
    for i in range(10):
        time.sleep(0.001)
        lock.acquire()   
        money.value -= 100
        lock.release()


if __name__ == '__main__':
    money = Value('i',2000) 
    lock = Lock() 


    d = Process(target=deposit,args=(money,lock))
    d.start()
    w = Process(target=withdraw,args=(money,lock))
    w.start()
    d.join()
    w.join()


    print(money.value)  


(3)
from multiprocessing import Process
import time
import os


class Proces:
    def __init__(set,interval):
        self.interval = interval


    def new_start(self):
        p = Process(target = self.run,args =())
        p.start()


        print('child process id is %d,name is %s' % (p.pid,p.name))
        
        print(os.getpriority(os.PRIO_PROCESS,p.pid))
        os.setpriority(os.PRIO_PROCESS,p.pid,1)        #获取进程改优先级
        print(os.getpriority(os.PRIO_PROCESS,p.pid))


        p.join()
        print('main process')


class Timer(Proces):
    def __init__(self,interval):
        self.interval = interval


    def run(self):  #打印时间的方法
        for i in range(5):
            time.sleep(self.interval)
            print(time.ctime()+'have a rest')
            
if __name__ == '__main__':
    t = Timer(2) #创建定时器

    t.new_start()   #继承process  do not call run   父类中函数会自动调用这个run方法


================================================================================================

相关代码:

设置优先级1-20,做一个模拟os的调度程序:某一时刻,四个进程:
Watch TV:          random优先级  import rnadom
Listen to music:   random优先级
Print Doc:         4
Write Doc:         4
创建队列,信息放进队列,模拟队列的调度(观察取数情况,验证时间片)


我的解法:
from queue import PriorityQueue 
# import random
# class Item(object):


#     def __init__(self,name,level):      #self 可以将属性写进去
#         self.name = name
#         self.level = level


#     def __repr__(self):
#         return (str(self.name) + ':' + str(self.level))


#     def __lt__(self,other):      #小于的比较 重写
#         return self.level > other.level


# if __name__ == '__main__':
#     q = PriorityQueue()
#     q.put(Item('watch tv',random.randint(1,20)))
#     q.put(Item('music',random.randint(1,20)))
#     q.put(Item('print',4))
#     q.put(Item('write',4))


#     while not q.empty():
#         print(q.get())


#===============================================================================================
多进程定期器:每一个小时,你的定时器提示你:不要coding,休息一下吧!
提示的同时显示当前进程的pid,name,os模块设置优先级


我的解法:


# from multiprocessing import Process
# import time


# def getTime(interval):
#     while True:
#         time.sleep(interval)
#         print(time.ctime())


# if __name__ == '__main__':
#     p = Process(target=getTime,args=(1,))
#     p.start()
#     print(p.name,p.pid)   #子进程 子进程的id


#     p.join()   #等待子进程结束 实际是阻塞
#     print('ending')    #由于子进程无线循环,由于join(),导致主进程无法运行,等待子进程结束,形成阻塞


#===============================================================================================


#显示进程id,优先级
# from multiprocessing import Process
# import time
# import os


# def getTime(interval):
#     while True:
#         time.sleep(interval)
#         print(time.ctime())


# if __name__ == '__main__':
#     p = Process(target=getTime,args=(1,))
#     p.start()
#     print('子进程的名字和id:',p.name,p.pid)   #子进程 子进程的id
    
#     print(os.getpriority(os.PRIO_PROCESS,p.pid))
#     os.setpriority(os.PRIO_PROCESS,p.pid,1)        #获取进程改优先级
#     print(os.getpriority(os.PRIO_PROCESS,p.pid))


#     p.join()   #等待子进程结束 实际是阻塞
#     print('ending')    #由于子进程无线循环,由于join(),导致主进程无法运行,等待子进程结束,形成阻塞


#===============================================================================================


#将定时器改成面向对象的形式@@@@@@@@@@@@@已经完成,在20171106代码文件中
# from multiprocessing import Process
# import time
# import os


# class Timer(Process):
#     def __init__(self,interval):
#         self.sleep = interval


#     def run(self):  #打印时间的方法
            time.sleep(interval)
            print(time.ctime()+'have a rest')
            print(os.getpriority(os.PRIO_PROCESS,p.pid))
            os.setpriority(os.PRIO_PROCESS,p.pid,1)        #获取进程改优先级
            print(os.getpriority(os.PRIO_PROCESS,p.pid))


#     if __name__ == '__main__':
#         t = Timer(3600) #创建定时器
#         t.start()   #继承process  do not call run   父类中函数会自动调用这个run方法


#===============================================================================================
#===============================================================================================


20171104作业 - 老师的解法


设置优先级1-20,做一个模拟os的调度程序:某一时刻,四个进程:
Watch TV:          random优先级  import rnadom
Listen to music:   random优先级
Print Doc:         4
Write Doc:         4
创建队列,信息放进队列,模拟队列的调度(观察取数情况,验证时间片)




# from queue import PriorityQueue 
# import random
# class Item(object):


#     def __init__(self,name,level):      #self 可以将属性写进去
#         self.name = name
#         self.level = level


#     def __repr__(self):
#         return (str(self.name) + ':' + str(self.level))


#     def __lt__(self,other):      #小于的比较 重写
#         return self.level > other.level


# if __name__ == '__main__':
#     q = PriorityQueue()
#     q.put(Item('watch tv',random.randint(1,20)))
#     q.put(Item('music',random.randint(1,20)))
#     q.put(Item('print',4))
#     q.put(Item('write',4))


#     while not q.empty():
#         print(q.get())


#     q.put(Item('print',4+q.qsize()))
#     q.put(Item('write',4+q.qsize()))


#===============================================================================================


20171104作业- 老师的解法


多进程定期器:每一个小时,你的定时器提示你:不要coding,休息一下吧!
提示的同时显示当前进程的pid,name,os模块设置优先级


# from multiprocessing import Process
# import time


# def getTime(interval):
#     while True:
#         time.sleep(interval)
#         print(time.ctime())


# if __name__ == '__main__':
#     p = Process(target=getTime,args=(1,))
#     p.start()
#     print(p.name,p.pid)   #子进程 子进程的id


#     p.join()   #等待子进程结束 实际是阻塞
#     print('ending')    #由于子进程无线循环,由于join(),导致主进程无法运行,等待子进程结束,形成阻塞


#==================================


#显示进程id,优先级
# from multiprocessing import Process
# import time
# import os


# def getTime(interval):
#     while True:
#         time.sleep(interval)
#         print(time.ctime())


# if __name__ == '__main__':
#     p = Process(target=getTime,args=(1,))
#     p.start()
#     print('子进程的名字和id:',p.name,p.pid)   #子进程 子进程的id
    
#     print(os.getpriority(os.PRIO_PROCESS,p.pid))
#     os.setpriority(os.PRIO_PROCESS,p.pid,1)        #获取进程改优先级
#     print(os.getpriority(os.PRIO_PROCESS,p.pid))


#     p.join()   #等待子进程结束 实际是阻塞
#     print('ending')    #由于子进程无线循环,由于join(),导致主进程无法运行,等待子进程结束,形成阻塞


#=================================


#将定时器改成面向对象的形式
# from multiprocessing import Process
# import time
# import os


# class Timer(Process):
#     def __init__(self,interval):
#         self.sleep = interval


#     def run(self):  #打印时间的方法
#             time.sleep(interval)
            # print(time.ctime()+'have a rest')
            # print(os.getpriority(os.PRIO_PROCESS,p.pid))
            # os.setpriority(os.PRIO_PROCESS,p.pid,1)        #获取进程改优先级
            # print(os.getpriority(os.PRIO_PROCESS,p.pid))


#     if __name__ == '__main__':
#         t = Timer(3600) #创建定时器
#         t.start()   #继承process  do not call run   父类中函数会自动调用这个run方法




#===============================================================================================
#===============================================================================================


20171106课堂练习代码


#生产消费模型


# from multiprocessing import Queue
# from multiprocessing import Process
# import time


# #消费者模型
# def consumer(input_q):
#     time.sleep(2)
#     while not input_q.empty():
#         print(input_q.get())


# #生产者逻辑
# def producer(sequence,output_p):
#     for i in sequence:
#         output_p.put(i)






# if __name__ == '__main__':
#     q= Queue()
#     con_p = Process(target=consumer,args=(q,))
#     con_p.start()


#     sequence =[1,2,3,4,5]
#     producer(sequence,q)


#=================================


#生产消费模型
# from multiprocessing import Queue
# from multiprocessing import Process
# import time


# #消费者模型
# def consumer(input_q):
#     time.sleep(2)
#     while True:
#         if not input_q.empty():
#             print(input_q.get())
#         else:
#             break
# #生产者逻辑
# def producer(sequence,output_p):
#     for i in sequence:
#         output_p.put(i)






# if __name__ == '__main__':
#     q= Queue()
#     con_p = Process(target=consumer,args=(q,))
#     con_p.start()


#     sequence =[1,2,3,4,5]
#     producer(sequence,q)


#=================================


# #生产消费模型 
# from multiprocessing import Queue
# from multiprocessing import Process
# import time


# #消费者模型
# def consumer(input_q):  #input_q  声明参数  从生产者那里拿走物品(数据,队列数据)
#     while True:
#         item = input_q.get()
#         if item == None:       #用None作为标志,判断生产者是否已经结束了生产
        
#             break
#         print(item)


# #生产者逻辑
# def producer(sequence,output_p):


#     for i in sequence:
#         time.sleep(1)
#         output_p.put(i)


# if __name__ == '__main__':
#     q= Queue()
#     con_p = Process(target=consumer,args=(q,))  #消费者进程 创建一个进程,进程的目标一定是个函数名,或者值类中的函数名即方法名,进程的参数
#     con_p.start()


#     sequence =[1,2,3,4,5]
#     # pro_p = Process(target=producer,args=(sequence,q))  #消费者进程
#     # pro_p.start()
#     producer(sequence,q)  #  生产者开始生产数字12345,放入队列中
    
#     q.put(None)     #  向队列中放入一个空值(或者说是生产一个空值),空值也是值,是一个特殊的值




#=================================




# #生产消费模型  队列  演示一个子进程既可以put 也可以get
# from multiprocessing import Queue
# from multiprocessing import Process
# import time


# #消费者模型
# def consumer(input_q):  #input_q  声明参数  从生产者那里拿走物品(数据,队列数据)
#     while True:
#         item = input_q.get()
#         if item == None:       #用None作为标志,判断生产者是否已经结束了生产
#             # input_q.put(6)
#             break
#         print(item)


# #生产者逻辑
# def producer(sequence,output_p):


#     for i in sequence:
#         time.sleep(1)
#         output_p.put(i)


# if __name__ == '__main__':
#     q= Queue()
#     con_p = Process(target=consumer,args=(q,))  #消费者进程 创建一个进程,进程的目标一定是个函数名,或者值类中的函数名即方法名,进程的参数
#     con_p.start()


#     sequence =[1,2,3,4,5]
#     # pro_p = Process(target=producer,args=(sequence,q))  #消费者进程
#     # pro_p.start()
#     producer(sequence,q)  #  生产者开始生产数字12345,放入队列中
    
#     # con_p.join()    #一定等子进程结束,保证consumer也能向队列中添加数字6 表明对列中子进程的双方既可以put,也可以get,而管道只能单向,一个子进程在定义管道后只能get或者put
#     q.put(None)     #  向队列中放入一个空值(或者说是生产一个空值),空值也是值,是一个特殊的值




#===============================================================================================


# #管道操作-仅了解
# from multiprocessing import Pipe
# from multiprocessing import Process


# #消费者模型
# def consumer(pipe):
#     (conn1,conn2) = pipe #两个变量构成一个管道,管道是设置的参数pipe
#     conn2.close()        #关闭管道的发送方!!!
#     while True:
#         try:
#             item = conn1.recv()
#             print(item)
#         except EOFError:         #文件读取错误
#             break
#     print('consumer ending done')
# #生产者逻辑
# def producer(sequence,sendPipe):
#     for i in sequence:
#         sendPipe.send(i)




# if __name__ == '__main__':
#     (conn1,conn2) = Pipe()  #创建管道,conn1是接收方  conn2是发送方
#     con_p = Process(target=consumer,args=((conn1,conn2),)) #创建消费者子进程,把管道(元组)作为参数传入;生产者为主进程
#     con_p.start()


#     conn1.close()  #关闭生产者的输出管道
#     sequence =[1,2,3,4,5]   #这里还要用到发送方
#     producer(sequence,conn2)
#     conn2.close()






#=================================


# #管道操作- 仅了解
# from multiprocessing import Pipe
# from multiprocessing import Process




# #消费者模型
# def consumer(pipe):
#     (conn1,conn2) = pipe 
#     conn2.close()
#     while True:
#         try:
#             item = conn1.recv()
#         except EOFError:
#             conn1.close()
#             break
#         print(item)
#     print('consumer ending done')


# #生产者逻辑
# def producer(sequence,sendPipe):
#     for i in sequence:
#         sendPipe.send(i)




# if __name__ == '__main__':
#     (conn1,conn2) = Pipe()  #创建管道,conn1是接收方  conn2是发送方
#     con_p = Process(target=consumer,args=((conn1,conn2),)) #创建消费者子进程,把管道(元组)作为参数传入;生产者为主进程
#     con_p.start()


#     conn1.close()  #关闭生产者的输出管道
#     sequence =[1,2,3,4,5]   #这里还要用到发送方
#     producer(sequence,conn2)
#     conn2.close()


#===============================================================================================


# #银行存取款demo1 正常


# from multiprocessing import Process
# from multiprocessing import Value   #在不同的进程间共享的变量
# import time


# def deposit(money):    #存钱
#     for i in range(100):
#         money.value += 1


# def withdraw(money):   #取钱
#     for i in range(100):
#         money.value -= 1


# if __name__ == '__main__':
#     money = Value('i',2000) #共享变量 int 数值2000
#     d = Process(target=deposit,args=(money,))
#     d.start()
#     w = Process(target=withdraw,args=(money,))
#     w.start()
    
#     d.join()
#     w.join()


#     print(money.value)    #三个进程一起跑 不一定会执行词句 需要等待子进程结束






#=================================


# #银行存取款demo1  - 存取款异常


前提知识1:多进程不能访问同一个全局变量,原因是不同的进程使用的虚拟内存空间不同,而全局变量实际是用的同一个内存空间,
因此需要 import Value 生成一个能够在不同的进程间共享和操作的变量


前提知识2:对于time.sleep ,在一个程序中,子进程之间会抢占资源,比如抢占 value ,看a在睡醒的时刻是否能够抢占到资源value


# from multiprocessing import Process
# from multiprocessing import Value   #在不同的进程间共享的变量
# import time


# def deposit(money):    #存钱
#     for i in range(100):
#         time.sleep(0.1)
#         money.value += 1


# def withdraw(money):   #取钱
#     for i in range(100):
#         time.sleep(0.1)
#         money.value -= 1


# if __name__ == '__main__':
#     money = Value('i',2000) #共享变量 int 数值2000
#     d = Process(target=deposit,args=(money,))
#     d.start()
#     w = Process(target=withdraw,args=(money,))
#     w.start()
    
#     d.join()
#     w.join()


#     print(money.value)    #三个进程一起跑 不一定会执行词句 需要等待子进程结束




#=================================


#银行存取款demo2 - 存取款异常-解决 —— 锁1
from multiprocessing import Process
from multiprocessing import Value   #在不同的进程间共享的变量
from multiprocessing import Lock
import time


def deposit(money,lock):    #存钱
    # lock.acquire()   #上锁的操作
    for i in range(100):
        time.sleep(10)
        money.value += 1
    # lock.release()


def withdraw(money,lock):   #取钱
    # lock.acquire()   #上锁的操作
    for i in range(100):
        time.sleep(0.0001)
        money.value -= 1
    # lock.release()


if __name__ == '__main__':
    money = Value('i',2000) #共享变量 int 数值2000
    lock = Lock() #银行为了安全 加了一把互斥锁


    d = Process(target=deposit,args=(money,lock))
    d.start()
    w = Process(target=withdraw,args=(money,lock))
    w.start()
    
    d.join()
    w.join()


    print(money.value)    #三个进程一起跑 不一定会执行词句 需要等待子进程结束




#=================================


# #银行存取款demo3 - 存取款异常-解决 —— 锁2 -更优 因为锁的力度更小,时间更短
# from multiprocessing import Process
# from multiprocessing import Value   #在不同的进程间共享的变量
# from multiprocessing import Lock
# import time


# def deposit(money,lock):    #存钱
    
#     for i in range(100):
#         time.sleep(0.1)
#         lock.acquire()   #上锁的操作
#         money.value += 1
#         lock.release()


# def withdraw(money,lock):   #取钱


#     for i in range(100):
#         time.sleep(0.1)
#         lock.acquire()   #上锁的操作
#         money.value -= 1
#         lock.release()


# if __name__ == '__main__':
#     money = Value('i',2000) #共享变量 int 数值2000
#     lock = Lock() #银行为了安全 加了一把互斥锁


#     d = Process(target=deposit,args=(money,lock))
#     d.start()
#     w = Process(target=withdraw,args=(money,lock))
#     w.start()
    
#     d.join()
#     w.join()


#     print(money.value)    #三个进程一起跑 不一定会执行词句 需要等待子进程结束,因此添加join方法

原创粉丝点击