Python AsyncIO

asyncio是从Python 3.4+开始引入的标准库,从而支持async IO,协程(coroutine)。

举个例子:假设有1个洗衣房,里面有10台洗衣机,有一个洗衣工在负责这10台洗衣机。那么洗衣房就相当于1个进程,洗衣工就相当1个线程。如果有10个洗衣工,就相当于10个线程,1个进程是可以开多线程的。这就是多线程!

那么协程呢?先不急。大家都知道,洗衣机洗衣服是需要等待时间的,如果10个洗衣工,1人负责1台洗衣机,这样效率肯定会提高,但是不觉得浪费资源吗?明明1 个人能做的事,却要10个人来做。只是把衣服放进去,打开开关,就没事做了,等衣服洗好再拿出来就可以了。就算很多人来洗衣服,1个人也足以应付了,开好第一台洗衣机,在等待的时候去开第二台洗衣机,再开第三台,……直到有衣服洗好了,就回来把衣服取出来,接着再取另一台的(哪台洗好先就取哪台,所以协程是无序的)。这就是计算机的协程!洗衣机就是执行的方法。

当你程序中方法需要等待时间的话,就可以用协程,效率高,消耗资源少。

好了!现在来总结一下:

洗衣房 ==> 进程

洗衣工 ==> 线程

洗衣机 ==> 方法(函数)

1. async await

函数前+async keyword时,实际上是创建了这个函数的wrapper,当调用这个函数时,实际上会返回一个coroutine object

首先 正常使用async awit

import asyncioasync def main():print("Hello World")print(main())
<coroutine object main at 0x7feada389ec0>
RuntimeWarning: coroutine 'main' was never awaitedprint(main())
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

coroutine object与正常function不同,如果要等待coroutine object的执行结果,需要使用keyword await来等待coroutine完成返回的结果。我们来试试await:

import asyncioasync def main():print("Hello World")await main()
File "/Users/xxx/PycharmProjects/pythonProject/test_ansy.py", line 15await main()^
SyntaxError: 'await' outside function

await 只能在async函数中使用。但是await要在async函数中使用,而要跑async函数,需要await等待返回结果。需要使用event-loop

2. Event-loop

Event-Loop是一个在程序中等待并分发事件或者消息的设计模式

Python coroutine需要跑在event-loop中

asyncio这个包中提供了一个asyncio.run的函数,可以作为coroutine的入口,asyncio.run会创建一个event-loop,然后将传递给他的coroutine object执行在这个event-loop上,通常asyncio.run这个函数在程序中只会被调用一次,作为coroutine的入口

import asyncio
async def main():print("Hello World")asyncio.run(main())
Hello World
import asyncio
async def main():print("Hello World")await foo("I am foo")print("foo done")async def foo(text):print(text)# 当前coroutine放弃运行,等待5秒后返回await asyncio.sleep(5)print("wake up")asyncio.run(main())
Hello World
I am foo
wake up
foo done

asyncio.new_event_loop()来创建一个新的Event-Loop然后通过loop.run_until_complete()来启动一个coroutine

import asyncioasync def main():print("Hello World")await foo("I am foo")print("foo done")async def foo(text):print(text)await asyncio.sleep(2)print("wake up foo")loop = asyncio.new_event_loop()
loop.run_until_complete(main())
Hello World
I am foo
wake up foo
foo done

3. task

当foo函数sleep的时候,我们不希望等待他结束,我们希望在此期间做一些别的事情,可以使用asyncio.create_task.asyncio.create_task 会获取当前正在运行的event-loop,然后再这个loop上schedule一个task。这个task会尽可能快的开始运行。Task是一个Future-like的object(Future后面会提到),这个object上运行着一个coroutine,Task存在的意义在于让用户在Event-Loop上运行coroutine。那么为什么说是尽可能快的呢?先看接下来这个例子

import asyncioasync def main():print("Hello World")task = asyncio.create_task(foo("I am foo"))print("foo done")await taskasync def foo(text):print(text)await asyncio.sleep(1)print("wake up")asyncio.run(main())
Hello World
foo done
I am foo
wake up

Surprise! “foo done"在"I am foo"之前被print了出来,这是因为create_task只是在Running Event-Loop上schedule了一个task,并没有立刻开始运行,因为main还没有暂停执行进入等待,也没执行结束,所以main会继续执行。当main执行到await task时,main暂停执行进入等待,下一个在Event-Loop上的task才开始执行,也就是foo。所以我们先看到了"foo done”,然后才是"I am foo"。接下来foo进入了sleep,暂停执行进入等待,而main()在等待foo的执行结果,Event-Loop上已经没有其他可以继续执行的task了,所以程序等待foo的asyncio.sleep(1)结束,最后print “wake up”。

以上这种scheduling的方式叫做cooperative scheduling,一个Event-Loop在同一时间只运行一个Task。当一个Task awaits另一个Task(Future)完成时,当前Task会暂时停止执行,等待Future的结果,然后Event-Loop会让别的Task,Future callback(后面有提到),或者IO开始执行。

这里就要提到asyncio.Future的定义了。

Future

asyncio.create_task的返回是task,task的定义是:

asyncio.tasksclass Task(Future[_T], Generic[_T])

future是

asyncio.futuresclass Future(Awaitable[_T], Iterable[_T])

Task它继承了Future,Future代表一个async operation在未来的最终结果。要等待这个task完成返回最终结果,我们可以使用前面提到的await keyword,这是因为Future是Awaitable的。

import asyncioasync def main():print("Hello World")task = asyncio.create_task(foo("I am foo"))await taskprint("foo done")async def foo(text):print(text)await asyncio.sleep(1)print("wake up")asyncio.run(main())
Hello World
I am foo
wake up
foo done

这里可以看到,main()中的await task让main等待foo执行结束后,才继续print “foo done”。

你可能还想问,我们如何获取到task的返回结果呢?:

import asyncioasync def main():task_foo = asyncio.create_task(foo("I am foo"))task_bar = asyncio.create_task(bar())foo_res = await task_fooawait task_barprint(foo_res)async def foo(text):print(text)await asyncio.sleep(4)print("wake up")return "returns " + textasync def bar():for i in range(10):print(i)await asyncio.sleep(1)asyncio.run(main())
I am foo
0
1
2
3
wake up
4
5
6
7
8
9
returns I am foo

res = await task 可以让task的返回值被赋予到res上。

Future同时也可以用来设置callback,当Future执行完成后,callback会被执行

import asyncioasync def main():task_foo = asyncio.create_task(foo("I am foo"))task_foo.add_done_callback(callback)foo_res = await task_fooprint(foo_res)async def foo(text):print(text)await asyncio.sleep(1)print("wake up")return "returns " + textdef callback(future):print("Future has result:", future.result())print("I am callback")asyncio.run(main())
I am foo
wake up
Future has result: returns I am foo
I am callback
returns I am foo

快速掌握AsyncIO---新手入门相关推荐

  1. 新手入门 如何快速找到Python进阶路线?

    新手入门 如何快速找到Python进阶路线?Python作为一种开放源代码的脚本编程语言,常用于开发各种程序.随着近几年人工智能的火爆,Python一度受到众多程序员的追捧,成为首选的入门编程语言.很 ...

  2. 计算机入门新人必学,电脑新手入门教程 让你快速上手

    随着互联网时代的快速发展,电脑发展也相当的成熟,新手学电脑可以快速入门,是每个新手梦寐以求的事情,但是不会所有人都可以快速上手,最近很多用户咨询我关于零基础学电脑先学什么,或者是电脑新手入门必学什么东 ...

  3. 快速理解j=j++ 和 j=++j(新手入门)

    快速理解j = j++ 和 j = ++ j(新手入门): j = j++ ,代码如下: public class TestDemo {/*** @param args*/public static ...

  4. 人工智能新手入门学习路线!附学习资源合集

    有段时间没跟大家分享编程资源福利了!今天为大家整理了人工智能新手入门学习路线,同时附700分钟的学习资源合集,相信这套福利可以帮你顺利入行AI!文末领取全部资料. 一.AI基础好课学习资料整理(约31 ...

  5. 【原创】新手入门一篇就够:从零开发移动端IM

    一.前言 IM发展至今,已是非常重要的互联网应用形态之一,尤其移动互联网时代,它正以无与论比的优势降低了沟通成本和沟通代价,对各种应用形态产生了深远影响. 做为IM开发者或即将成为IM开发者的技术人员 ...

  6. 课程上线 -“新手入门 : Windows Phone 8.1 开发”

    经过近1个月的准备和录制,"新手入门 : Windows Phone 8.1 开发"系列课程已经在Microsoft 虚拟学院上线,链接地址为:http://www.microso ...

  7. 新手入门机器学习十大算法

    新手入门机器学习十大算法 2018年9月17日 磐石 TensorFlowNews, 机器学习 0 在机器学习的世界中,有一种被称为"无免费午餐"的定理. 它意在说明没有哪种算法能 ...

  8. Windows学习总结(6)——MindManager新手入门教程

    2019独角兽企业重金招聘Python工程师标准>>> MindManager新手入门教程 MindManager是一款创造.管理和交流思想的思维导图软件,其直观清晰的可视化界面和强 ...

  9. Docker新手入门:基本用法

    Docker新手入门:基本用法 1.Docker简介 1.1 第一本Docker书 工作中不断碰到Docker,今天终于算是正式开始学习了.在挑选系统学习Docker以及虚拟化技术的书籍时还碰到了不少 ...

  10. 如何学习Linux / 新手入门

    如何学习Linux / 新手入门 一.从基础开始:常常有些朋友在Linux论坛问一些问题,不过,其中大多数的问题都是很基础的.例如:为什么我使用一个命令的时候,系统告诉我找不到该目录,我要如何限制使用 ...

最新文章

  1. lookout筛选相同信息_信息流广告4大行业案例总结分析(不会操作那就抄吧,建议收藏)...
  2. h5文字垂直居中_CSS实现居中的几种方式你都了解吗?
  3. 爬虫智能解析库 Readability 和 Newspaper 的用法
  4. 互联网公司的黑话,你都经历过吗?
  5. html----选项卡自动切换以及鼠标悬停时停止(js)
  6. 绚丽的javascript拾色器(不兼容IE8及以下)
  7. WinRar注册机或注册码
  8. easypoi 语法_【语法微课合集】50堂英语语法微课,视频课件免费下载,建议收藏或转发朋友圈...
  9. CSS动画文字闪烁问题
  10. 车联网TCU USB的配置和使用
  11. VLC模拟TS直播流
  12. 全国大学生数学建模竞赛(建模全过程)
  13. 【Netty官方文档翻译】引用计数对象(reference counted objects)
  14. element表格左对齐方法
  15. 什么是c语言系统调用,什么是系统调用?为什么要用系统调用?
  16. 巴贝奇计算机科学思想,计算机之父巴贝奇_图灵_计算机科学之父
  17. php对接第三方接口
  18. Spring Cloud Config教程(四)快速开始
  19. 支付宝生活缴费视频课程
  20. 完全禁止WIN10自动更新的方法

热门文章

  1. 率土服务器维护多久,率土之滨维护需要多久,维护多久201820月24
  2. 转载 藏经阁第2卷-SQL常用的函数
  3. CodeForces 156C Cipher
  4. 2022最新微软MOS认证考试报名备考攻略
  5. StarRocks斩获「2022 掘金引力榜」年度技术品牌传播案例 Top 10!
  6. 【Linux】shell脚本实现多并发
  7. IM即时通讯哇呼--解析
  8. 江西省工艺美术师陈海清老师*
  9. Android ScrollView去掉右侧滑动条
  10. Linux进程和任务管理和分析和排查系统故障