python异步IO编程(一)

基础概念

异步IO (async IO):一种由多种语言实现的与语言无关的范例(或模型)。

asyncio:Python 3.4版本引入的标准库,直接内置了对异步IO的支持。

异步IO

线程,多线程

多线程善于处理I/O密集型任务。

多进程擅长处理计算密集型(CPU-bound)任务:强密集循环和数学计算都属于此类。

并发是并行的一种特殊类型(或者说子类),多线程是并发的表现形式,多进程是并行的表现形式。

Python通过它的包 multiprocessing,threading 和 concurrent.futures 已经对这两种形式都提供了长期的支持。

异步IO

异步IO是一种单进程、单线程的设计:它使用协同多任务处理机制,是以协程为核心的一种编程模型。

异步IO并不是新发明的概念,它已经存在或正在被构建到其他语言及运行时环境中,如 Go,C# 和 Scala 等。

异步IO模型异步IO采用消息循环的模式,在消息循环中,主线程不断地重复“读取消息-处理消息”这一过程:

loop = get_event_loop() //实例消息队列whileTrue:

event= loop.get_event() //从队列中读取消息

process_event(event)//处理消息消息模型其实早在应用在桌面应用程序中了。一个GUI程序的主线程就负责不停地读取消息并处理消息。所有的键盘、鼠标等消息都被发送到GUI程序的消息队列中,然后由GUI程序的主线程处理。

由于GUI线程处理键盘、鼠标等消息的速度非常快,所以用户感觉不到延迟。某些时候,GUI线程在一个消息处理的过程中遇到问题导致一次消息处理时间过长,此时,用户会感觉到整个GUI程序停止响应了,敲键盘、点鼠标都没有反应。

这种情况说明在消息模型中,处理一个消息必须非常迅速,否则,主线程将无法及时处理消息队列中的其他消息,导致程序看上去停止响应。

消息模型是如何解决同步IO必须等待IO操作这一问题的呢?当遇到IO操作时,代码只负责发出IO请求,不等待IO结果,然后直接结束本轮消息处理,进入下一轮消息处理过程。当IO操作完成后,将收到一条“IO完成”的消息,处理该消息时就可以直接获取IO操作结果。

在“发出IO请求”到收到“IO完成”的这段时间里,同步IO模型下,主线程只能挂起,但异步IO模型下,主线程并没有休息,而是在消息循环中继续处理其他消息。这样,在异步IO模型下,一个线程就可以同时处理多个IO请求,并且没有切换线程的操作。对于大多数IO密集型的应用程序,使用异步IO将大大提升系统的多任务处理能力。

asyncio

async与asyncio.coroutine

在 python3.5 中,创建一个协程仅仅只需使用 async 关键字,而python3.4使用 @asyncio.coroutine 装饰器。都引入了原生协程或者说异步生成器。下面的任一代码,都可以作为协程工作,形式上也是等同的:

importasyncio

asyncdef ping_server(ip): #3.5

pass@asyncio.coroutinedef load_file(path): #3.4

pass

yield from与await

3.1 中协程操作只是简单的生成器调用,常见的我们还需要在生成器或者说协程之间相互调用,用到yield from。yield from 用于一个generator调用另一个generator,主要是为了generator之间的调用。

yield from 表达式的使用方式如下:

importasyncio

@asyncio.coroutinedefget_jason(client, url):

file_content= yield from load_file('/Usrs/scott/data.txt')

协程的一个关键特性是它们可以被链接到一起。(记住,一个协程是可等待的,所以另一个协程可以使用 await 来等待它。)await 将控制器传递给时间循环。(挂起当前运行的协程与yield from类似),使用方式如下:

async defping_local(ip):return await ping_server('192.168.1.1')

Python3.5 对这两种调用协程的方法都提供了支持,但是推荐 async/await 作为首选。

Python执行的时候, g() 函数范围内如果遇到表达式 await f(),就是 await 在告诉事件循环“挂起 g() 函数,直到 f() 返回结果,在此期间,可以运行其他函数。”

async defg():#暂停,直到 f()结束再回到g()

r =await f()return r

当你使用 await f() 时,要求 f() 是一个可等待的对象。但这并没有什么用。现在,只需要知道可等待对象要么是(1)其他的协程,要么就是(2)定义了 .await() 函数且返回迭代器的对象。如果你正在编写程序,绝大多数情况只需要关注案例#1。

使用规则

1. 使用 await 与 return 的组合创建协程函数。想要调用一个协程函数,必须使用 await 等待返回结果。

2. 在 async def 代码块中使用 yield 的情况并不多见(只有Python的近期版本才可用)。当你使用 async for 进行迭代的时候,会创建一个异步生成器。暂时先忘掉异步生成器,将目光放在使用 await 与 return 的组合创建协程函数的语法上。

3. 在任何使用 async def 定义的地方都不可以使用 yield from,这会引发异常 SyntaxError。

4. 一如在 def 定义的函数之外使用 yield 会引发异常 SyntaxError,在 async def 定义的协程之外使用 await 也会引发异常 SyntaxError。你只能在协程内部使用 await。

Event Loop

asyncio的编程模型就是一个消息循环。我们从asyncio模块中直接获取一个EventLoop的引用,然后把需要执行的协程扔到EventLoop中执行,就实现了异步IO。

用asyncio实现Hello world代码如下:

importasyncio

@asyncio.coroutinedefhello():print("Hello world!")#异步调用asyncio.sleep(1):

r = yield from asyncio.sleep(1)print("Hello again!")#获取EventLoop:

loop =asyncio.get_event_loop()#执行coroutine

loop.run_until_complete(hello())

loop.close()

@asyncio.coroutine把一个generator标记为coroutine类型,然后,我们就把这个coroutine扔到EventLoop中执行。

hello()会首先打印出Hello world!,然后,yield from语法可以让我们方便地调用另一个generator。由于asyncio.sleep()也是一个coroutine,所以线程不会等待asyncio.sleep(),而是直接中断并执行下一个消息循环。当asyncio.sleep()返回时,线程就可以从yield from拿到返回值(此处是None),然后接着执行下一行语句。

把asyncio.sleep(1)看成是一个耗时1秒的IO操作,在此期间,主线程并未等待,而是去执行EventLoop中其他可以执行的coroutine了,因此可以实现并发执行。

async/await版本:

importasyncio

asyncdefhello():print("Hello World")

r= await asyncio.sleep(1)print("Again")

loop=asyncio.get_event_loop()

loop.run_until_complete(hello())

loop.close()

我们用Task封装两个coroutine试试:

importthreadingimportasyncio

@asyncio.coroutinedefhello():print('Hello world! (%s)' %threading.currentThread())yield from asyncio.sleep(1)print('Hello again! (%s)' %threading.currentThread())

loop=asyncio.get_event_loop()

tasks=[hello(), hello()]

loop.run_until_complete(asyncio.wait(tasks))

loop.close()

观察执行过程:

Hello world! (<_MainThread(MainThread, started 140735195337472)>)

Hello world! (<_MainThread(MainThread, started 140735195337472)>)

(暂停约1秒)

Hello again! (<_MainThread(MainThread, started 140735195337472)>)

Hello again! (<_MainThread(MainThread, started 140735195337472)>)

由打印的当前线程名称可以看出,两个coroutine是由同一个线程并发执行的。

如果把asyncio.sleep()换成真正的IO操作,则多个coroutine就可以由一个线程并发执行。

参考:

python 异步io_python异步IO编程(一)相关推荐

  1. python程序官方网站-IO编程

    IO在计算机中指Input/Output,也就是输入和输出.由于程序和运行时数据是在内存中驻留,由CPU这个超快的计算核心来执行,涉及到数据交换的地方,通常是磁盘.网络等,就需要IO接口. 比如你打开 ...

  2. Python自学笔记D9——IO编程、进程、线程和正则表达式

    文章目录 IO编程 文件读写 StringIO和BytesIO 操作文件和目录 序列化 进程和线程 多进程 多线程 ThreadLocal 多进程和多线程对比 分布式进程 正则表达式 IO编程 由于程 ...

  3. Python学习笔记十 IO编程

    参考教程:廖雪峰官网https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000 IO编程 I ...

  4. Python学习笔记:Io编程序列化

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  5. Python学习笔记:IO编程StringIO和BytesIO

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  6. java 异步模型_Java IO编程全解(三)——伪异步IO编程

    为了解决同步阻塞I/O面临的一个链路需要一个线程处理的问题,后来有人对它的线程模型进行了优化,后端通过一个线程池来处理多个客户端的请求接入,形成客户端个数M:线程池最大线程数N的比例关系,其中M可以远 ...

  7. python 网络编程 异步io_python网络编程——网络IO模型

    服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: (1)同步阻塞IO(Blocking IO):即传统的IO模型. (2)同步非阻塞IO(Non-blocking IO):默认创建的s ...

  8. io密集型和cpu密集型_一次说明白Python爬虫中多线程,多进程,异步IO编程

    图/文:迷神 我们在Python爬虫中,重要的是讲究速度,如果有10万或者100万Url地址,写过爬虫的都会知道,那估计是非常慢的.我们的Python爬虫一般IO密集型业务,Python爬虫程序需要发 ...

  9. python 异步io 写excel_python异步IO编程(二)

    python异步IO编程(二) 目录 开门见山 Async IO设计模式 事件循环 asyncio 中的其他顶层函数 开门见山 下面我们用两个简单的例子来让你对异步IO有所了解 importasync ...

最新文章

  1. ubuntu12.04下android开发环境搭建两个注意事项
  2. Intellij Idea/Webstorm/Phpstorm 的高效快捷键
  3. 【项目管理】Scrum内容整理
  4. 对于计算机文化的总结,计算机文化基础一级总结
  5. 如何判断自己的编程水平
  6. 做技术知道了哪些事情代表自己成熟了?
  7. 个人计算机的防毒软件无法防御,在win10系统中无法启动defender防御软件的解决方法...
  8. 编程大白给编程小白的四点建议
  9. [转载] python不允许使用关键字_Python中关键字global与nonlocal的区别
  10. HTML5来了,7个混合式移动开发框架
  11. [Android1.5]标签TabHost图片文字覆盖的问题
  12. android网络测试上传速度慢,【教程】状态栏添加网速 《双排上传速度和下载速度》(转)...
  13. go语言循环基础练习
  14. python调用chrome插件_使用Python开发chrome插件
  15. 小明身高180cm,小刚身高165cm,计算两人的身高差
  16. 数据结构视频知识点整理 1
  17. MyISAM InnoDB 怎么读
  18. 国内外学习科学研究机构简介…
  19. Word 2010 找不到 Endnote选项
  20. Node-RED教程(一):Node-RED的介绍与安装

热门文章

  1. moreclipboard能记录多个粘贴内容的eclipse粘贴板插件
  2. 800乘600的分辨率_600元能买到啥配置的手机?
  3. vue ---- webpack中的插件 webpack-dev-server
  4. 计算机真题11Excel,计算机网考真题EXCELPPT操作题答案(11页)-原创力文档
  5. faststart可以卸载吗_你的手机你做主!免 ROOT 卸载安卓手机预装APP
  6. CentOS7安装minio
  7. 玩转iOS开发:iOS 8 新特性《UIVisualEffect》
  8. HDU3308 线段树区间合并
  9. 对软件测试团队“核心价值”的思考
  10. CHM文件打开显示乱码的解决方法