python 的进程池、管道、队列

进程池的map使用

  1. p.apply()是指让进程池中的进程,同步的帮你做任务
    2.p.apply_async()# 是指让进程池中的进程,异步的帮你做任务
from multiprocessing import Pool

def func(num):
    num += 1
    print(num)
    return num

if __name__ == '__main__':
    p = Pool(5)
    res = p.map(func,[i for i in range(100)])
    p.close()
    p.join()
    print('主进程中map的返回值',res)

函数回调的使用


from multiprocessing import Pool
import requests
import time,os

def func(url):
    res = requests.get(url)
    print('子进程的pid:%s,父进程的pid:%s'%(os.getpid(),os.getppid()))
    # print(res.text)
    if res.status_code == 200:
        return url,res.text

def cal_back(sta):
    url,text = sta
    print('回调函数的pid', os.getpid())
    with open('a.txt','a',encoding='utf-8') as f:
        f.write(url + text)
    # print('回调函数中!',url)

if __name__ == '__main__':
    p = Pool(5)
    l = ['https://www.baidu.com',
         'http://www.jd.com',
         'http://www.taobao.com',
         'http://www.mi.com',
         'http://www.cnblogs.com',
         'https://www.bilibili.com',
         ]
    print('主进程的pid',os.getpid())
    for i in l:
        p.apply_async(func, args=(i,),callback=cal_back)#
        # 异步执行任务func,每有一个进程执行完任务后,在func中return一个结果,结果会自动的被callback指定的函数,当成形式参数来接收到
    p.close()
    p.join()

管道的使用

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()# 生产完数据,关闭父进程这一端的管道

Manager 进程之间共享数据

from multiprocessing import Process,Manager


def func(num):
    num[2] -= 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)

Queue 队列

from multiprocessing import Queue

q = Queue(3)

q.put(1)
q.put('abc')
q.put([4,5,6])
# print(123)
# q.put('汉子')
# try:
#     q.put_nowait('汉子')
# except:
#     print('队列满了')
# print(456)

print(q.get())
print(q.get())
print(q.get())
# print(q.get())# 阻塞等待
try:
    print(q.get_nowait())
except:
    print('队列空了')

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()

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

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个进程,主进程和生产者进程和消费者进程。
  当主进程执行到35行代码时,主进程会等待生产进程结束
    # 而生产进程中(第26行)会等待消费者进程把所有数据消费完,
生产者进程才结束。
    # 现在的状态就是  主进程等待生产者进程结束,
生产者进程等待消费者消费完所有数据
    # 所以,把消费者设置为守护进程。 
 当主进程执行完,就代表生产进程已经结束,也就代表消费者进程已经把队列中数据消费完
    # 此时,主进程一旦结束,守护进程也就是消费者进程也就跟着结束。    整个程序也就能正常结束了。


你可能感兴趣的:(python 的进程池、管道、队列)