python 3.4

>>> import asyncio
>>> from datetime import datetime
>>> @asyncio.coroutine
... def baby(num):
... print('baby {} sleep at {}'.format(num,datetime.now().timestamp()))
... r = yield from asyncio.sleep(1)
... print(r,'--',datetime.now().timestamp())
... print('baby {} wake up at {}'.format(num,datetime.now().timestamp()))
...
>>> # 获取异步时间循环
... loop = asyncio.get_event_loop()
>>> # 定义一个任务列表
... tasklist = [baby(1),baby(2),baby(3)]
>>> # 开启协程
... loop.run_until_complete(asyncio.wait(tasklist)) baby 2 sleep at 1531723171.664242
baby 1 sleep at 1531723171.664458
baby 3 sleep at 1531723171.664564
None -- 1531723172.67095
baby 2 wake up at 1531723172.671148
None -- 1531723172.671252
baby 1 wake up at 1531723172.671377
None -- 1531723172.671462
baby 3 wake up at 1531723172.671585

python 3.5

用asyncio提供的@asyncio.coroutine可以把一个generator标记为coroutine类型,然后在coroutine内部用yield from调用另一个coroutine实现异步操作。

为了简化并更好地标识异步IO,从Python 3.5开始引入了新的语法async和await,可以让coroutine的代码更简洁易读。

请注意,async和await是针对coroutine的新语法,要使用新的语法,只需要做两步简单的替换:

把@asyncio.coroutine替换为async;
把yield from替换为await。 import asyncio
from datetime import datetime
from threading import current_thread
async def baby(num):
print('baby {} sleep at {} with thread name ({})'.format(num,datetime.now().timestamp(),current_thread().name))
r = await asyncio.sleep(2)
print('baby {} wake up at {} with thread name ({})'.format(num,datetime.now().timestamp(),current_thread().name))
loop = asyncio.get_event_loop()
tasklist = [baby(1),baby(2),baby(3)]
loop.run_until_complete(asyncio.wait(tasklist))
# 编写一个HTTP服务器,分别处理以下URL:

# / - 首页返回b'<h1>Index</h1>';

# /hello/{name} - 根据URL参数返回文本hello, %s!。

import asyncio

from aiohttp import web

async def index(request):
await asyncio.sleep(0.5)
return web.Response(body='<h1>Index</h1>'.encode(), content_type='text/html') async def hello(request):
await asyncio.sleep(0.5)
text = '<h1>hello, %s!</h1>' % request.match_info['name']
return web.Response(body=text.encode('utf-8')) async def init(loop):
app = web.Application(loop=loop)
app.router.add_route('GET', '/', index)
app.router.add_route('GET', '/hello/{name}', hello)
srv = await loop.create_server(app.make_handler(), '192.168.0.16', 9000)
print('Server started at http://192.168.0.16:9000...')
return srv loop = asyncio.get_event_loop()
loop.run_until_complete(init(loop))
loop.run_forever()

扩展知识

POSIX
同步IO、异步IO、阻塞IO、非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下。 POSIX(可移植操作系统接口)把同步IO操作定义为导致进程阻塞直到IO完成的操作,反之则是异步IO
按POSIX的描述似乎把同步和阻塞划等号,异步和非阻塞划等号,但是为什么有的人说同步IO不等于阻塞IO呢?先来说说几种常见的IO模型吧。 IO模型
这里统一使用Linux下的系统调用recv作为例子,它用于从套接字上接收一个消息,因为是一个系统调用,所以调用时会从用户进程空间切换到内核空间运行一段时间再切换回来。默认情况下recv会等到网络数据到达并且复制到用户进程空间或者发生错误时返回,而第4个参数flags可以让它马上返回。 阻塞IO模型
使用recv的默认参数一直等数据直到拷贝到用户空间,这段时间内进程始终阻塞。A同学用杯子装水,打开水龙头装满水然后离开。这一过程就可以看成是使用了阻塞IO模型,因为如果水龙头没有水,他也要等到有水并装满杯子才能离开去做别的事情。很显然,这种IO模型是同步的。 image 非阻塞IO模型
改变flags,让recv不管有没有获取到数据都返回,如果没有数据那么一段时间后再调用recv看看,如此循环。B同学也用杯子装水,打开水龙头后发现没有水,它离开了,过一会他又拿着杯子来看看……在中间离开的这些时间里,B同学离开了装水现场(回到用户进程空间),可以做他自己的事情。这就是非阻塞IO模型。但是它只有是检查无数据的时候是非阻塞的,在数据到达的时候依然要等待复制数据到用户空间(等着水将水杯装满),因此它还是同步IO。 image IO复用模型
这里在调用recv前先调用select或者poll,这2个系统调用都可以在内核准备好数据(网络数据到达内核)时告知用户进程,这个时候再调用recv一定是有数据的。因此这一过程中它是阻塞于select或poll,而没有阻塞于recv,有人将非阻塞IO定义成在读写操作时没有阻塞于系统调用的IO操作(不包括数据从内核复制到用户空间时的阻塞,因为这相对于网络IO来说确实很短暂),如果按这样理解,这种IO模型也能称之为非阻塞IO模型,但是按POSIX来看,它也是同步IO,那么也和楼上一样称之为同步非阻塞IO吧。 这种IO模型比较特别,分个段。因为它能同时监听多个文件描述符(fd)。这个时候C同学来装水,发现有一排水龙头,舍管阿姨告诉他这些水龙头都还没有水,等有水了告诉他。于是等啊等(select调用中),过了一会阿姨告诉他有水了,但不知道是哪个水龙头有水,自己看吧。于是C同学一个个打开,往杯子里装水(recv)。这里再顺便说说鼎鼎大名的epoll(高性能的代名词啊),epoll也属于IO复用模型,主要区别在于舍管阿姨会告诉C同学哪几个水龙头有水了,不需要一个个打开看(当然还有其它区别)。 image 信号驱动IO模型
通过调用sigaction注册信号函数,等内核数据准备好的时候系统中断当前程序,执行信号函数(在这里面调用recv)。D同学让舍管阿姨等有水的时候通知他(注册信号函数),没多久D同学得知有水了,跑去装水。是不是很像异步IO?很遗憾,它还是同步IO(省不了装水的时间啊)。 image 异步IO模型
调用aio_read,让内核等数据准备好,并且复制到用户进程空间后执行事先指定好的函数。E同学让舍管阿姨将杯子装满水后通知他。整个过程E同学都可以做别的事情(没有recv),这才是真正的异步IO。 image 总结
IO分两阶段: 1.数据准备阶段
2.内核空间复制回用户进程缓冲区阶段
一般来讲:阻塞IO模型、非阻塞IO模型、IO复用模型(select/poll/epoll)、信号驱动IO模型都属于同步IO,因为阶段2是阻塞的(尽管时间很短)。只有异步IO模型是符合POSIX异步IO操作含义的,不管在阶段1还是阶段2都可以干别的事。 ps:以上图片均截自UNIX网络编程卷1。

python -- 异步IO 协程的更多相关文章

  1. python异步加协程获取比特币市场信息

    目标 选取几个比特币交易量大的几个交易平台,查看对应的API,获取该市场下货币对的ticker和depth信息.我们从网站上选取4个交易平台:bitfinex.okex.binance.gdax.对应 ...

  2. 异步IO/协程/数据库/队列/缓存(转)

    原文:Python之路,Day9 - 异步IO\数据库\队列\缓存 作者:金角大王Alex add by zhj: 文章很长 引子 到目前为止,我们已经学了网络并发编程的2个套路, 多进程,多线程,这 ...

  3. 2020.11.2 异步IO 协程

    异步IO 同步IO在一个线程中,CPU执行代码的速度极快,然而,一旦遇到IO操作,如读写文件.发送网络数据时,就需要等待IO操作完成,才能继续进行下一步操作. 在IO操作的过程中,当前线程被挂起,而其 ...

  4. 第十一章:Python高级编程-协程和异步IO

    第十一章:Python高级编程-协程和异步IO Python3高级核心技术97讲 笔记 目录 第十一章:Python高级编程-协程和异步IO 11.1 并发.并行.同步.异步.阻塞.非阻塞 11.2 ...

  5. Python实现基于协程的异步爬虫

    一.课程介绍 1. 课程来源 本课程核心部分来自<500 lines or less>项目,作者是来自 MongoDB 的工程师 A. Jesse Jiryu Davis 与 Python ...

  6. Python - 异步IO\数据库\队列\缓存

    协程 协程,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程,协程一定是在单线程运行的. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和 ...

  7. Python基础之协程

    阅读目录 一 引子 二 协程介绍 三 Greenlet模块 四 Gevent模块 引子 之前我们学习了线程.进程的概念,了解了在操作系统中 进程是资源分配的最小单位,线程是CPU调度的最小单位. 按道 ...

  8. python线程、协程、I/O多路复用

    目录: 并发多线程 协程 I/O多路复用(未完成,待续) 一.并发多线程 1.线程简述: 一条流水线的执行过程是一个线程,一条流水线必须属于一个车间,一个车间的运行过程就是一个进程(一个进程内至少一个 ...

  9. 协程及Python中的协程

    1 协程 1.1协程的概念 协程,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程.(其实并没有说明白~) 我觉得单说协程,比较抽象,如果对线程有一定了解 ...

随机推荐

  1. Docker 网络部分的简单学习以及转帖别人的blog

    1. 感谢一下 大神: http://www.cnblogs.com/sparkdev/ 最近有时间的话 就会读一下他的博客.学习了解docker相关的知识 今天简单做了下 测试 在这里面记录一下. ...

  2. (一) 关于配置travis-ci持续集成python pytest测试的相关记录

    首先由于公司用上了高大上的travis-ci商用版,一直想试着学学弄弄看.现在要写openapi的相关测试,而且要在travis-ci上集成.我就想体验一下这个过程.所以自己弄了一个public的仓库 ...

  3. Java之JSON操作(gson)

    使用gson包操作JSON数据. 依赖包:gson-2.8.2.jar <dependency> <groupId>com.google.code.gson</group ...

  4. Lodop打印控件里SET_PRINT_STYLE和SET_PRINT_STYLEA

    LODOP.SET_PRINT_STYLE 对该语句后面的打印项样式设置效果.LODOP.SET_PRINT_STYLEA 针对第一个参数设置的打印项样式设置效果.这两个语句,作用范围不同. 在设置字 ...

  5. 企业网管用linux搭建邮件服务器为公司降本增效

    在企业中,节约一分钱比挣一分钱容易得多,这是指导企业降本增效的名言之一啊,作为一名企业里的IT人员我是深有感触,尤其是IT方面,除了在互联网公司是生产力的排头兵,在制造业单位里那一般都是后勤保障部门, ...

  6. BZOJ4822[Cqoi2017]老C的任务——树状数组(二维数点)

    题目描述 老 C 是个程序员.     最近老 C 从老板那里接到了一个任务——给城市中的手机基站写个管理系统.作为经验丰富的程序员,老 C 轻松 地完成了系统的大部分功能,并把其中一个功能交给你来实 ...

  7. BZOJ2795&2890&3647[Poi2012]A Horrible Poem——hash

    题目描述 给出一个由小写英文字母组成的字符串S,再给出q个询问,要求回答S某个子串的最短循环节.如果字符串B是字符串A的循环节,那么A可以由B重复若干次得到. 输入 第一行一个正整数n (n<= ...

  8. BZOJ2001 HNOI2010城市建设(线段树分治+LCT)

    一个很显然的思路是把边按时间段拆开线段树分治一下,用lct维护MST.理论上复杂度是O((M+Q)logNlogQ),实际常数爆炸T成狗.正解写不动了. #include<iostream> ...

  9. P3760 [TJOI2017]异或和

    题目描述 在加里敦中学的小明最近爱上了数学竞赛,很多数学竞赛的题都是与序列的连续和相关的.所以对于一个序列,求出它们所有的连续和来说,小明觉得十分的简单.但今天小明遇到了一个序列和的难题,这个题目不仅 ...

  10. Java 8新特性之 Base64(八恶人-7)

    "General" 我是个将军 “ You, sir a hyena. I hava no wish to speak to you.”  “你就是一个土狗,你不配跟我说话” 一. ...