【第52天】python全栈从入门到放弃

1 使用Manage()函数可以同步子进程和父进程

不是用Manage()

代码块
from multiprocessing import Process

def func(num,name):
    num[0] -= 1
    name='nezha'
    print('子进程中的num的值是',num,'子进程中的name的值是',name)

if __name__ == '__main__':
    m = Manager()
    num =[1,2,3]
    name='wangsiyu'
    p = Process(target=func,args=(num,name,))
    p.start()
    p.join()
    print('父进程中的num的值是',num,'进父程中的name的值是',name)

使用Manage()

代码块
from multiprocessing import Process,Manager

def func(num):
    num[0] -= 1
    print('子进程中的num的值是',num)

if __name__ == '__main__':
    m = Manager()
    num = m.list([1,2,3])
    p = Process(target=func,args=(num,))
    p.start()
    p.join()
    print('父进程中的num的值是',num)

2 队列Queue的简单应用

Queue的put

代码块
from multiprocessing import Queue

q=Queue(3)

q.put(123)
q.put(456)
q.put(789)

try:
    q.put_nowait('byebye')
except:
    print('队列满了')

Queue的get

代码块
from multiprocessing import Queue

q=Queue(3)

q.put(123)
q.put(456)
q.put(789)

print(q.get())
print(q.get())
print(q.get())   #此时,队列中的东西已经拿完了

try:
    print(q.get_nowait())
except:
    print('队列空了')

3 栈与队列

栈:先进后出(First In Last Out 简称 FILO)
队列: 先进先出(First In First Out 简称 FIFO)

4 对列实现生产者消费者模型

代码块
from multiprocessing import Queue,Process
import time

def consumer(q,name):
    while 1:
        info = q.get()
        if info:
            print('%s 拿走了%s'%(name,info))
        else:# 当消费者获得队列中数据时,如果获得的是None,就是获得到了生产者不再生产数据的标识
            break# 此时消费者结束即可

# 消费者如何判断,生产者是没来得及生产数据,还是生产者不再生产数据了?
# 如果你尝试用get_nowait() + try 的方式去尝试获得生产者不再生产数据,此时是有问题的。

def producer(q,product):
    for i in range(20):
        info = product + '的娃娃%s号'%str(i)
        q.put(info)
    q.put(None)# 让生产者生产完数据后,给消费者一个不再生产数据的标识

if __name__ == '__main__':
    q = Queue(10)
    p_pro = Process(target=producer,args=(q,'岛国米饭保你爱'))
    p_con = Process(target=consumer,args=(q,'alex'))
    p_pro.start()
    p_con.start()

5. 生产者消费者模型二

代码块
from multiprocessing import Queue,Process
import time

def consumer(q,name,color):
    while 1:
        info = q.get()
        if info:
            print('%s %s 拿走了%s \033[0m'%(color,name,info))
        else:# 当消费者获得队列中数据时,如果获得的是None,就是获得到了生产者不再生产数据的标识
            break# 此时消费者结束即可


def producer(q,product):
    for i in range(20):
        info = product + '的娃娃%s号'%str(i)
        q.put(info)

if __name__ == '__main__':
    q = Queue(10)
    p_pro1 = Process(target=producer,args=(q,'岛国米饭保你爱'))
    p_pro2 = Process(target=producer,args=(q,'苍老师版'))
    p_pro3 = Process(target=producer,args=(q,'波多多版'))
    p_con1 = Process(target=consumer,args=(q,'alex','\033[31m'))
    p_con2 = Process(target=consumer,args=(q,'wusir','\033[32m'))
    p_l = [p_con1,p_con2,p_pro1,p_pro2,p_pro3]
    [i.start() for i in p_l]
    # 父进程如何感知到生产者子进程不再生产数据了?
    p_pro1.join()
    p_pro2.join()
    p_pro3.join()
    q.put(None)# 几个消费者就要接受几个结束标识
    q.put(None)

6 使用joinablequeue()实现生产者消费者模型三

代码块
from multiprocessing import Process,JoinableQueue

q = JoinableQueue()

# q.join()# 用于生产者。等待 q.task_done的返回结果,通过返回结果,生产者就能获得消费者当前消费了多少个数据
# q.task_done() # 用于消费者,是指每消费队列中一个数据,就给join返回一个标识。

# 假设生产者生产了100个数据,join就能记录下100这个数字。每次消费者消费一个数据,就必须要task_done返回一个标识,
# 当生产者(join)接收到100个消费者返回来的标识的时候,生产者就能知道消费者已经把所有数据都消费完了。

from multiprocessing import Queue,Process
import time

def consumer(q,name,color):
    while 1:
        info = q.get()
        print('%s %s 拿走了%s \033[0m'%(color,name,info))
        q.task_done()

def producer(q,product):
    for i in range(20):
        info = product + '的娃娃%s号'%str(i)
        q.put(info)
    q.join()# 记录了生产了20个数据在队列中,此时会阻塞等待消费者消费完队列中所有数据

if __name__ == '__main__':
    q = JoinableQueue(10)
    p_pro1 = Process(target=producer,args=(q,'岛国米饭保你爱'))
    p_con1 = Process(target=consumer,args=(q,'alex','\033[31m'))
    p_con1.daemon = True# 把消费者进程设为守护进程
    p_con1.start()
    p_pro1.start()
    p_pro1.join()# 主进程等待生产者进程结束
    # 程序有3个进程,主进程和生产者进程和消费者进程。  当主进程执行到33行代码时,主进程会等待生产进程结束
    # 而生产进程中(第24行)会等待消费者进程把所有数据消费完,生产者进程才结束。
    # 现在的状态就是  主进程等待生产者进程结束,生产者进程等待消费者消费完所有数据
    # 所以,把消费者设置为守护进程。  当主进程执行完,就代表生产进程已经结束,也就代表消费者进程已经把队列中数据消费完
    # 此时,主进程一旦结束,守护进程也就是消费者进程也就跟着结束。    整个程序也就能正常结束了。


7单进程下的管道

代码块
from multiprocessing import Pipe

con1,con2 = Pipe()

con1.send('abc')
print(con2.recv())
con2.send(123)
print(con1.recv())

8 多进程下的管道

代码块
from multiprocessing import Pipe,Process
#管道是不安全的
def func(con):
    con1,con2 = con
    con1.close()# 子进程使用con2和父进程通信,所以
    while 1:
        try:
            print(con2.recv())#当主进程的con1发数据时,子进程要死循环的去接收。
        except EOFError:# 如果主进程的con1发完数据并关闭con1,子进程的con2继续接收时,就会报错,使用try的方式,获取错误
            con2.close()# 获取到错误,就是指子进程已经把管道中所有数据都接收完了,所以用这种方式去关闭管道
            break

if __name__ == '__main__':
    con1,con2 = Pipe()
    p = Process(target=func,args=((con1,con2),))
    p.start()
    con2.close()# 在父进程中,使用con1去和子进程通信,所以不需要con2,就提前关闭
    for i in range(10):# 生产数据
        con1.send(i)# 给子进程的con2发送数据
    con1.close()# 生产完数据,关闭父进程这一端的管道

9 import Queue 不能进行多进程之间的数据传输

from multiprocessing import Queue 借助Queue解决生产者消费者模型
队列是安全的。

q = Queue(num)
num : 队列的最大长度
q.get()# 阻塞等待获取数据,如果有数据直接获取,如果没有数据,阻塞等待
q.put()# 阻塞,如果可以继续往队列中放数据,就直接放,不能放就阻塞等待

q.get_nowait()# 不阻塞,如果有数据直接获取,没有数据就报错
q.put_nowait()# 不阻塞,如果可以继续往队列中放数据,就直接放,不能放就报错

10 from multiprocessing import JoinableQueue#可连接的队列

代码块
from multiprocessing import JoinableQueue#可连接的队列

JoinableQueue是继承Queue,所以可以使用Queue中的方法并且JoinableQueue又多了两个方法
       
q.join()# 用于生产者。等待 q.task_done的返回结果,通过返回结果,生产者就能获得消费者当前消费了多少个数据
       
q.task_done() # 用于消费者,是指每消费队列中一个数据,就给join返回一个标识。

11 管道Pipe

管道(了解)
from multiprocessing import Pipe
con1,con2 = Pipe()
管道是不安全的。
管道是用于多进程之间通信的一种方式。
如果在单进程中使用管道,那么就是con1收数据,就是con2发数据。
如果是con1发数据,就是con2收数据

如果在多进程中使用管道,那么就必须是
父进程使用con1收,子进程就必须使用con2发,
父进程使用con1发,子进程就必须使用con2收
父进程使用con2收,子进程就必须使用con1发
父进程使用con2发,子进程就必须使用con1收
在管道中有一个著名的错误叫做EOFError。是指,父进程中如果关闭了发送端,子进程还继续接收数据,那么就会引发EOFError。


别跑,点个赞再走

你可能感兴趣的:(【第52天】python全栈从入门到放弃)