本篇内容主要讲解“Python协程asyncio的作用是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Python协程asyncio的作用是什么”吧!
一、协程
官方描述;
协程是子例程的更一般形式。 子例程可以在某一点进入并在另一点退出。 协程则可以在许多不同的点上进入、退出和恢复。 它们可通过 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())
]
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'
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',
'https://www3.autoimg.cn/newsdfs/g26/M02/35/A9/120x90_0_autohomecar__ChsEe12AXQ6AOOH_AAFocMs8nzU621.jpg',
'https://www3.autoimg.cn/newsdfs/g26/M02/35/A9/120x90_0_autohomecar__ChsEe12AXQ6AOOH_AAFocMs8nzU621.jpg',
'https://www3.autoimg.cn/newsdfs/g26/M02/35/A9/120x90_0_autohomecar__ChsEe12AXQ6AOOH_AAFocMs8nzU621.jpg',
]
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的作用是什么”有了更深的了解,不妨来实际操作一番吧!这里是天达云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!