博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python进阶:并发编程之Asyncio
阅读量:5157 次
发布时间:2019-06-13

本文共 3145 字,大约阅读时间需要 10 分钟。

什么是Asyncio

  多线程有诸多优点且应用广泛,但也存在一定的局限性: 比如,多线程运行过程容易被打断,因此有可能出现 race condition 的情况;再如,线程切换本身存在一定的损耗,线程数不能无限增加,因此,如果I/O 操作非常 heavy,多线程很有可能满足不了高效率、高质量的需求。
  因此,Asyncio 应运而生。

Sync(同步) VS Async(异步)

  所谓 Sync,是指操作一个接一个地执行,下一个操作必须等上一个操作完成后才能执行。而 Async 是指不同操作间可以相互交替执行,如果其中的某个操作被 block 了,程序并不会等待,而是会找出可执行的操作继续执行。

Asyncio 工作原理

  Asyncio 和其他 Python 程序一样,是单线程的,它只有一个主线程,但是可以进行多个不同的任务(task),这里的任务,就是特殊的 future 对象。这些不同的任务,被一个叫做 event loop 的对象所控制。event loop 会根据其是否完成,把任务放到预备或等待状态的列表,然后遍历等待状态列表的任务,查看他们是否完成。如果完成,则将其放到预备状态的列表; 如果未完成,则继续放在等待状态的列表。

Asyncio 用法

import asyncioimport aiohttpimport timeasync def download_one(url):    async with aiohttp.ClientSession() as session:        async with session.get(url) as resp:            print('Read {} from {}'.format(resp.content_length, url))            #text_len = await resp.text()            #print('Read {} from {}'.format(len(text_len), url))            #print('len(text_len)',len(text_len))async def download_all(sites):    tasks = [asyncio.create_task(download_one(site)) for site in sites]    await asyncio.gather(*tasks)def main():    sites = [            'https://www.baidu.com/',            'https://pypi.org/',            'https://www.sina.com.cn/',            'https://www.163.com/',            'https://news.qq.com/',            'http://www.ifeng.com/',            'http://www.ce.cn/',            'https://news.baidu.com/',            'http://www.people.com.cn/',            'http://www.ce.cn/',            'https://news.163.com/',            'http://news.sohu.com/'    ]    start_time = time.perf_counter()    asyncio.run(download_all(sites))    end_time = time.perf_counter()    print('Download {} sites in {} seconds'.format(len(sites), end_time - start_time))    if __name__ == '__main__':    main()# 输出Read 227 from https://www.baidu.com/Read None from http://www.ce.cn/Read None from http://www.ce.cn/Read 38914 from http://www.people.com.cn/Read None from https://news.qq.com/Read None from https://news.163.com/Read None from https://www.163.com/Read 129268 from https://www.sina.com.cn/Read None from http://www.ifeng.com/Read None from https://news.baidu.com/Read None from http://news.sohu.com/Read 4293 from https://pypi.org/Download 12 sites in 0.7875643999999999 seconds
  主函数里的 asyncio.run(coro) 是 Asyncio 的 root call,表示拿到 event loop,运行输入的 coro,直到它结束,最后关闭这个 event loop。
  事实上,asyncio.run() 是 Python3.7+ 才引入的,相当于老版本的以下语句:
loop = asyncio.get_event_loop()try:    loop.run_until_complete(coro)finally:    loop.close()

Asyncio 有缺陷吗?

  首先有兼容性问题,如asyncio 与 requests库不兼容,因此上例使用的是aiohttp库(上例aiohttp库出现content_length为None,暂不知原因).另外是任务调度的问题,你需要 await 一系列的操作,就得使用 asyncio.gather();如果只是单个的 future,或许只用 asyncio.wait() 就可以了。那么,对于你的 future,你是想要让它 run_until_complete() 还是 run_forever() 呢?

Asyncio 还是 多线程?

  可以遵循以下伪代码的规范:

if io_bound:    if io_slow:        print('Use Asyncio')    else:        print('Use multi-threading')else if cpu_bound:    print('Use multi-processing')
  • 如果是 I/O bound,并且 I/O 操作很慢,需要很多任务 / 线程协同实现,那么使用 Asyncio 更合适。
  • 如果是 I/O bound,但是 I/O 操作很快,只需要有限数量的任务 / 线程,那么使用多线程就可以了。
  • 如果是 CPU bound,则需要使用多进程来提高程序运行效率。

参考

  极客时间《Python核心技术与实战》专栏

 

转载于:https://www.cnblogs.com/xiaoguanqiu/p/11166504.html

你可能感兴趣的文章
软件测试笔试题目
查看>>
直线段的扫描转换算法
查看>>
MyBatis一次执行多条SQL语句
查看>>
安卓环境搭建
查看>>
bzoj2038 [2009国家集训队]小Z的袜子(hose)
查看>>
bzoj2333 [SCOI2011]棘手的操作
查看>>
在ASP.NET Atlas中创建自定义的Behavior
查看>>
ant安装与配置
查看>>
福彩双色球项目
查看>>
20162330 结对编程项目-四则运算(挑战出题)
查看>>
【Linux】awk详细介绍
查看>>
顶级(top-level)元素,块级(block-level)元素和内联(inline)元素.
查看>>
折腾Java设计模式之模板方法模式
查看>>
简明python教程笔记一
查看>>
672. Bulb Switcher II 灯泡切换器II
查看>>
二十三、CI框架之post
查看>>
LCS待完成
查看>>
JavaScript-实现下拉菜单
查看>>
docker搭建mysql集群
查看>>
比天空还远的季节
查看>>