首页 > 编程语言 > 详细

python-协程二(创建协程)

时间:2020-03-29 00:40:44      阅读:89      评论:0      收藏:0      [点我收藏+]

一、协程在python中常用的包

  yieldgreenletgeventasyncio

 

二、创建协程

  1)使用yield创建协程

import time


def consumer(name):  # 生成器
    print("%s 要开始吃包子了!" % name)
    while True:
        baozi=yield    # 暂停,记录位置,返回跳出(接收下面send发送的数据,接收到数据后才会继续执行)
        print("包子%s,%s吃了"%(baozi,name))


def producer(name):
    c = consumer("消费者")   # 只是变成一个生成器
    c.__next__()       # next只唤醒yield不传递值
    for i in range(4):
        time.sleep(1)
        print("%s 做了包子%s"%(name,i))
        c.send(i)  # 发送数据


if __name__ == "__main__":
    producer("生产者")

结果:
消费者 要开始吃包子了!
生产者 做了包子0
包子0,消费者吃了
生产者 做了包子1
包子1,消费者吃了
生产者 做了包子2
包子2,消费者吃了
生产者 做了包子3
包子3,消费者吃了

 

  2)使用greenlet创建协程

from greenlet import greenlet


def proc1():
    print(12)
    gr2.switch()  # 执行权切换到gr2,gr1暂停执行
    print(34)
    gr2.switch()  # 执行权切换到gr2,gr1将从刚才暂停的地方继续执行


def proc2():
    print(56)
    gr1.switch()  # 执行权切换到gr1,gr1将从刚才暂停的地方继续执行,gr2暂停执行
    print(78)


if __name__ == "__main__":
    gr1 = greenlet(proc1)  # 启动协程1
    gr2 = greenlet(proc2)  # 启动协程2
    gr1.switch()  # 先执行gr1指定运行的函数

结果:
12
56
34
78

  3)使用gevent创建协程

from gevent import monkey; monkey.patch_all()  # 这个代表遇到IO就移交执行权,不用等待
import gevent
import requests


def f(url):
    print(GET: %s % url)
    resp = requests.get(url)  # 网络IO会切换执行权
    data = resp.text
    print(%d bytes received from %s. % (len(data), url))


gevent.joinall([
        gevent.spawn(f, https://www.baidu.com/),
        gevent.spawn(f, https://www.sina.com.cn/),
        gevent.spawn(f, https://sohu.com/),
])

结果:
GET: https://www.baidu.com/
GET: https://www.sina.com.cn/
GET: https://sohu.com/
537854 bytes received from https://www.sina.com.cn/.
2443 bytes received from https://www.baidu.com/.
177385 bytes received from https://sohu.com/.
结论:当遇到IO的时候,就切换执行权了,去执行其他任务,然后等网络IO写回来再继续往下执行
import gevent import requests def f(url): print(GET: %s % url) resp = requests.get(url) # 网络IO会切换执行权 data = resp.text print(%d bytes received from %s. % (len(data), url)) gevent.joinall([ gevent.spawn(f, https://www.baidu.com/), gevent.spawn(f, https://www.sina.com.cn/), gevent.spawn(f, https://sohu.com/), ]) 结果: GET: https://www.baidu.com/ 2443 bytes received from https://www.baidu.com/. GET: https://www.sina.com.cn/ 537846 bytes received from https://www.sina.com.cn/. GET: https://sohu.com/ 177385 bytes received from https://sohu.com/. 结论:如果没有monkey.patch_all(),那么协程会一个一个任务的执行,当遇到IO的时候,它也会等待内容返回,再去执行下一个任务

  3)使用asyncio创建协程

import time
import asyncio

‘‘‘
单协程实例
‘‘‘

now = time.time()  # 返回当前时间戳


async def do_some_work(x):  # 定义协程任务,前缀必须要写async
    print(Waiting: , x)
    time.sleep(x)

if __name__ == "__main__":
    start = time.time()
    coroutine1 = do_some_work(2)  # 把协程任务的对象存放到变量里
    coroutine2 = do_some_work(3)
    loop = asyncio.get_event_loop()  # 创建一个事件循环
    loop.run_until_complete(coroutine1)  # 把协程注册到事件循环,并启动事件循环
    loop.run_until_complete(coroutine2)  # 把协程注册到事件循环,并启动事件循环
    print(TIME: , time.time() - start)

结果:
Waiting:  2
Waiting:  3
TIME:  5.001837491989136
import time
import asyncio

‘‘‘
绑定回调
‘‘‘


async def do_some_work(x):  # 协程任务,前缀async
    print(Waiting: , x)
    return Done after {}s.format(x)


def callback(a):  # a 代表协程任务的对象
    print(Callback: , a.result())  # a.result() 固定写法,获取协程任务的返回值。


if __name__ == "__main__":
    start = time.time()
    coroutine = do_some_work(2)  # 把协程任务的对象存放到变量里
    loop = asyncio.get_event_loop()  # 把协程注册到事件循环,并启动事件循环
    task = asyncio.ensure_future(coroutine)  # 创建一个task
    task.add_done_callback(callback)  # 绑定回调
    loop.run_until_complete(task)  # 把test注册到事件循环,并启动事件循环
    print(TIME: , time.time() - start)

结果:

Waiting: 2
Callback: Done after 2s
TIME: 0.0009970664978027344

 

python-协程二(创建协程)

原文:https://www.cnblogs.com/su-sir/p/12590231.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!