• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

浅谈Python协程asyncio

python 搞代码 4年前 (2022-01-08) 52次浏览 已收录 0个评论
文章目录[隐藏]

今天给大家带来的是关于Python的相关知识,文章围绕着Python协程展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下

一、协程

官方描述;
协程是子例程的更一般形式。 子例程可以在某一点进入并在另一点退出。 协程则可以在许多不同的点上进入、退出和恢复。 它们可通过 async def 语句来实现。 参见 PEP 492。

  • 协程不是计算机内部提供的,不像进程、线程,由电脑本身提供,它是由程序员人为创造的, 实现函数异步执行。
  • 协程(Coroutine),也可以被称为微线程,是一种用户太内的上下文切换技术,其实就是通过一个线程实现代码块相互切换执行。看上去像子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。例如:
 # 需要python3.7+ import asyncio async def main(): print('hello') await asyncio.sleep(1) print('world') asyncio.run(main()) # 打印 "hello",等待 1 秒,再打印 "world" 

注意:简单地调用一个协程并不会使其被调度执行,

直接main() 调用会有问题:

 RuntimeWarning: coroutine 'main' was never awaited main() RuntimeWarning: Enable tracemalloc to get the object allocation traceback
 def func1(): print(1) ... print(2) def func2(): print(3) ... print(4) func1() func2() # 结果:1 2 3 4

实现协程的方法:

  • greenlet,早期模块【不建议使用】
  • yield关键字,它是python的生成器,具有保存状态,切换到其他函数去执行,再切换回原函数的功能。
  • asyncio装饰器(python3.4引入)
  • async、await 关键字(python3.5)【推荐使用】

1.1 greenlet实现协程

 # 第三方模块,因此需要安装 pip install greenlet
 from greenlet import greenlet def func1(): print(1) gr2.switch() print(2) gr2.switch() def func2(): print(3) gr1.switch() print(4) gr1 = greenlet(func1) gr2 = greenlet(func2) gr1.switch() # 结果:1 3 2 4 

1.2 yield关键字

 def func1(): yield 1 yield from func2() yield 2 def func2(): yield 3 yield 4 f1 = func1() for item in f1: print(item) # 结果:1 3 2 4 

1.3 asynico装饰器

python3.4 及之后版本支持

DeprecationWarning: “@coroutine” decorator is deprecated since Python 3.8, use “async def”
翻译:@coroutine”装饰器自Python 3.8起已弃用,请使用”async def”代替

所以这个也不支持。

 import asyncio @asyncio.coroutine def func1(): print(1) yield from asyncio.sleep(2)  # 遇到IO耗时操作,自动切换到tasks中其他任务,比如:网络IO,下载图片 print(2) @asyncio.coroutine def func2(): print(3) yield from asyncio.sleep(2)  # 遇到IO耗时操作,自动切换到tasks中其他任务,比如:网络IO,下载图片 print(4) tasks = [ asyncio.ensure_future(func1()), asyncio.ensure_future(func2()) ]<span style="color:transparent">来源gaodai#ma#com搞*!代#%^码网</span> loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.wait(tasks)) # 结果: 1 3 2 4 

1.4 async & await 关键字

 import asyncio async def func1(): print(1) await asyncio.sleep(2)  # 遇到IO耗时操作,自动切换到tasks中其他任务,比如:网络IO,下载图片 print(2) async def func2(): print(3) await asyncio.sleep(2)  # 遇到IO耗时操作,自动切换到tasks中其他任务,比如:网络IO,下载图片 print(4) tasks = [ asyncio.ensure_future(func1()), asyncio.ensure_future(func2()) ] loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.wait(tasks)) 

二、协程的意义

充分利用线程。在一个线程中如果遇到IO等待时间线程不会一直等待,利用空闲时间再去干点其他事情。

以下载三张图片为例:

普通方式(同步)下载:

 import time import requests def download_image(url, img_name): print("开始下载:", url) # 发送网络请求,下载图片 response = requests.get(url) print("下载完成") # 图片保存到本地文件 file_name = str(img_name) + '.png-600' with open(file_name, mode='wb') as file: file.write(response.content) if __name__ == '__main__': start = time.time() url_list = [ 'https://tse4-mm.cn.bing.net/th/id/OIP.866vRxQ8QvyDsrUuXiu7qwHaNK?w=182&h=324&c=7&o=5&pid=1.7', 'https://tse2-mm.cn.bing.net/th/id/OIP.HUcWtoYPG-z2pu4ityajbAHaKQ?w=182&h=252&c=7&o=5&pid=1.7', 'https://tse2-mm.cn.bing.net/th/id/OIP.MvncR0-Pt9hVxKTdrvD9dAHaNK?w=182&h=324&c=7&o=5&pid=1.7', 'https://tse1-mm.cn.bing.net/th/id/OIP._nGloaeMWbL7NB7Lp6SnXQHaLH?w=182&h=273&c=7&o=5&pid=1.7', ] img_name = 1 for item in url_list: download_image(item, img_name) img_name += 1 end = time.time() print(end - start) # 最终时间:7.25s 

协程方式(异步)下载:

 import aiohttp import asyncio import time async def fetch(session, url): print("发送请求:", url) async with session.get(url, verify_ssl=False) as response: content = await response.content.read() file_name = url.rsplit('_')[-1] # print(file_name) with open(file_name, mode='wb') as file_object: file_object.write(content) print("下载完成") async def main(): async with aiohttp.ClientSession() as session: url_list = [ 'https://www3.autoimg.cn/newsdfs/g26/M02/35/A9/120x90_0_autohomecar__ChsEe12AXQ6AOOH_AAFocMs8nzU621.jpg-600', 'https://www3.autoimg.cn/newsdfs/g26/M02/35/A9/120x90_0_autohomecar__ChsEe12AXQ6AOOH_AAFocMs8nzU621.jpg-600', 'https://www3.autoimg.cn/newsdfs/g26/M02/35/A9/120x90_0_autohomecar__ChsEe12AXQ6AOOH_AAFocMs8nzU621.jpg-600', 'https://www3.autoimg.cn/newsdfs/g26/M02/35/A9/120x90_0_autohomecar__ChsEe12AXQ6AOOH_AAFocMs8nzU621.jpg-600', ] tasks = [asyncio.ensure_future(fetch(session, url)) for url in url_list] await asyncio.wait(tasks) if __name__ == '__main__': start = time.time() asyncio.get_event_loop().run_until_complete(main()) end = time.time() print(end - start) # 结果:0.05s 

以上就是浅谈Python协程asyncio的详细内容,更多请关注gaodaima搞代码网其它相关文章!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:浅谈Python协程asyncio

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址