python-利用生成器实现并发

1.创建一个生成器:
next和send都可以使生成器对象输出。
区别在send可以传值。

def create_num(all_num):
    print('-----1-------')
    a, b = 0, 1
    current_num = 0
    while current_num < all_num:
        print('-----2-----')
        ret = yield a
        print('>>>>ret>>>>',ret)
        print('-----3------')
        a, b = b, a + b
        current_num += 1
        print('-----4------')

    return 'ok'


obj1 = create_num(100)
print('obj1:',obj1)
red = next(obj1)
print(red)
red1 = obj1.send('python')
print(red1)

在这里插入图片描述

2.生成器的应用:实现多任务

import time

def task_1():
    while True:
        print('-----1-------')
        time.sleep(0.1)
        yield


def task_2():
    while True:
        print('-------2---------')
        time.sleep(0.1)
        yield

# task_1()
# task_2()

def main():
    t1 = task_1()
    t2 = task_2()
    """
    类似于两个while True一起执行
    先让t1运行一会,当t1遇到yield的时候,再返回到18行
    然后执行t2,当它遇到yield的时候,再次切换到t1中
    这样t1/t2/t1/t2的交替运行,最终实现了多任务---->协程
    """
    while True:
        next(t1)
        next(t2)

main()

"""
并行:有两个任务,两个cpu,一个任务占一个cpu
并发:有四个任务,两个cpu,四个任务交替占有cpu执行,我们这里实现的都是并发
"""

3.yield实现单线程并发

上面的例子定义了两个函数,是多线程的并发那么怎么让单线程并发呢?

利用了关键字yield一次性返回一个结果,阻塞,重新开始
send 唤醒
这个例子实现了单线程两个函数同时并发。

import time
def consumer(name):
    print('%s 准备学习了' % (name))
    while True:
        lesson = yield
        print('开始[%s]了,[%s]老师来讲课了' % (lesson, name))

def producer(name):
    c1 = consumer('A')  # 并发 调用函数,打印AB准备学习了,到yield暂停
    c2 = consumer('B')
    c1.__next__()  # 与函数外next的同理只是格式不同,让consumer程序从yield循环一次。yield输出值none这里没有打印,所以没有输出。
    c2.__next__()
    print('同学们开始上课了')
    for i in range(10):
        time.sleep(0.1)
        print('到了两个同学')
        c1.send(i)  # 将i传递给断点处  lesson = 0 ,这里满足了send不在第一个,next的none是yield的第一个输出。
        c2.send(i)  # 并发lesson = 0

producer('westos')

在这里插入图片描述

4.使用greenlet完成多任务
为了更好的使用协程来完成多任务,python中的greeblet模块
对其进行的封装
首先先在系统里安装greenlet
在这里插入图片描述

from greenlet import greenlet

import time


def test1():
    while True:
        print('---A---')
        gr2.switch()  # 与test2交替进行,当test1暂停的时候,执行test2,
                      # test2暂停时执行test1
        time.sleep(0.5)


def test2():
    while True:
        print('---B---')
        gr1.switch()
        time.sleep(0.5)


gr1 = greenlet(test1)
gr2 = greenlet(test2)

gr1.switch()		#这里一定要到按这个格式调用函数

在这里插入图片描述

5.使用gevent完成多任务
和greenlet一样,先下在gevent第三方库
在这里插入图片描述gevent也能实现函数的交替进行,当一个函数暂停时运行下一个。
这里为了看出效果,我们让f3不睡眠,f1,f2睡眠。
可以看出f1睡眠0.5s时运行f2,f2睡眠0.5s运行f3,
因为f3不睡眠所以运行到结束才会接着运行f1。

 import gevent

def f1(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        gevent.sleep(0.5)

def f2(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        gevent.sleep(0.5)
def f3(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        #gevent.sleep(0.5)  f3函数不睡眠0.5秒

g1 = gevent.spawn(f1,5)
g2 = gevent.spawn(f2,5)
g3 = gevent.spawn(f3,5)

g1.join()
g2.join()
g3.join()

在这里插入图片描述
从结果可以看出f3()运行完才继续交替运行f1,f2.

6.利用并行可以进行同时下载网页的多个图片
首先,学习一下单张图片的下载。
首先选择你要下载的图片–>按f12显示web代码–>找到图片对应的网址
在这里插入图片描述
找到图片地址,以jpg结尾。
https://img30.360buyimg.com/vc/jfs/t26584/137/2237011912/642049/b9bd9596/5bfb9442Ncb0c29fc.jpg

import urllib.request

def main():
    req = urllib.request.urlopen('https://img30.360buyimg.com/vc/jfs/t26584/137/2237011912/642049/b9bd9596/5bfb9442Ncb0c29fc.jpg')
    img_content = req.read()
    with open('python.jpg','wb') as f:	#定一个图片名为python
        f.write(img_content)

main()

可以在当前文件夹下看见多了一个名为python的文件
在这里插入图片描述

图片下载成功
在这里插入图片描述

可以利用gevent一次下载多张图片:

import urllib.request
import gevent
from gevent import monkey

def downloder(img_name,img_url):
    req = urllib.request.urlopen(img_url)
    img_content = req.read()
    with open(img_name,'wb') as f:
        f.write(img_content)

def main():
    gevent.joinall([
        gevent.spawn(downloder,'2.jpg','https://img3.doubanio.com/view/photo/m/public/p2528834770.jpg'),
        gevent.spawn(downloder,'3.jpg','https://img1.doubanio.com/view/photo/l/public/p2541840518.jpg'),
        gevent.spawn(downloder,'4.jpg','https://img3.doubanio.com/view/photo/l/public/p2540519750.jpg')
    ])
main()

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43067754/article/details/84954518
今日推荐