python协程

协成实质上是子线程的特例
传统的子线程或者叫做函数之间的调用关系是线性的,统一用栈这种解构来管理。而协程打破了这种调用关系,协程在线程中切换的时候可以是任意的,由于协程是在一个线程之中进行切换,统一使用同一个线程级别的执行上下文,所以没有昂贵的线程切换造成的系统开销,并且也不会产生资源竞争的问题。
先看一下协成是如何被使用的:
def consumer():
r =”
while True:
n = yield r
if not n:
return
print(‘consuming %s’ %n)
r = ‘ok’
def produce(c):
c.send(None)
n = 0
while n<5:
n = n+1
print(‘produceing %s’ %n)
r = c.send(n)
print(‘consumer return:%s’ %r)
c.close()
c = consumer()
produce(c)

结果
produceing 1
consuming 1
consumer return:ok
produceing 2
consuming 2
consumer return:ok
produceing 3
consuming 3
consumer return:ok
produceing 4
consuming 4
consumer return:ok
produceing 5
consuming 5
consumer return:ok

生产者子线程运行,通过send方法启动消费者子线程(一个生成器),消费者子线程返回接着执行生产者子线程,这次生产了参数1,通过send方法传给了消费者子线程,消费者子线程通过yield获取到参数1经过处理,还是通过yield将处理后的数据经过send返回给生产者子线程。
拥有这样的特性的协程能够解决什么问题呢?
1.异步io
由于cpu计算的速度远远大于磁盘,网络io的速度,所以在传统io模型中,当某个线程处在一个CPU时间片中,且线程中有一个耗时的io操作时,这个时候cpu必须等待io操作完成才能执行下一步代码,这就造成了cpu空闲。python3标准库中引入了异步io模型asyncio(基于协程)
先看代码:
import asyncio

@asyncio.coroutine
def test():
print(‘start’)
#异步调用asyncio.sleep(5)
yield from asyncio.sleep(5)
print(‘5秒之后’)
#获取event_loop
loop = asyncio.get_event_loop()
#执行协程
tasks = [test(),test()]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()

@asyncio.coroutine把一个generator标记为coroutine类型,然后,我们就把这个coroutine扔到EventLoop中执行,由
于asyncio.sleep()也是一个coroutine,所以线程不会等待asyncio.sleep(),而是直接中断并执行下一个消息循环。
当asyncio.sleep()返回时,线程就可以从yield from拿到返回值(此处是None),然后接着执行下一行语句。。使用数组来模拟并发情景。然后将asyncio。sleep换成真正的io操作。就可以实现多个协程由一个线程并发执行了。

使用异步io技术实现支持并发访问的服务器

在上面的基础上很容易实现一个由协成支持的并发服务器了,看代码:
import asyncio,os,json,time
from datetime import datetime
from aiohttp import web

def index(request):
response = web.Response(body=b’

Awesome

‘)
# 如果不添加content_type,某些严谨的浏览器会把网页当成文件下载,而不是直接显示
response.content_type = ‘text/html;charset=utf-8’
return response

@asyncio.coroutine
def init(loop):
app = web.Application(loop=loop)
app.router.add_route(‘GET’,’/’,index)
srv = yield from loop.create_server(app.make_handler(),’127.0.0.1’,9000)
print(‘server start’)
return srv
loop = asyncio.get_event_loop()
loop.run_until_complete(init(loop))
loop.run_forever()

只需要增加app中的访问路径就ok了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值