协程
- 不是计算机提供,程序员人为创造
- 也称为微线程,是一种上下文切换技术(通过一个线程实现代码块互相切换执行)
- 普通代码的执行流程自上而下顺序执行
def fun1():
print(1)
# ...
print(2)
def fun2():
print(3)
# ...
print(4)
fun1()
fun2()
- 结果: 等fun1执行完,再执行fun2
-
实现方法
- greenlet: 早期模块
- yield 关键字
- asyncio装饰器(py3.4开始支持)
- async,await关键字(py3.5开始支持,推荐)
-
greenlet实现协程
from greenlet import greenlet
def fun1():
print(1)
gr2.switch() # 跳转到fun2
print(2)
gr2.switch()
def fun2():
print(3)
gr1.switch() # 跳转到fun1
print(4)
gr1 = greenlet(fun1)
gr2 = greenlet(fun2)
gr1.switch() # 开始执行
- 返回结果:
1
3
2
4
- yield示例
def fun1():
yield 1
yield from fun2() # 切换到 fun2
yield 2
def fun2():
yield 3
yield 4
f1 = fun1()
for item in f1:
print(item)
- 返回结果:
1
3
4
2
- asyncio示例
import asyncio
# 先定义两个协程对象
@asyncio.coroutine
def fun1():
print(1)
# 这里不能直接 asyncio.sleep(2)(报错信息: coroutine 'sleep' was never awaited)
yield from asyncio.sleep(2)
print(2)
@asyncio.coroutine
def fun2():
print(3)
yield from asyncio.sleep(2)
print(4)
# 创建任务
tasks = [
asyncio.ensure_future(fun1()),
asyncio.ensure_future(fun2())
]
# 创建'轮询对象'并执行任务
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
- async & await示例
import asyncio
async def fun1(): # 协程函数对象
print(1)
await asyncio.sleep(2) # 等的时候切换到其他代码块并执行
print(2)
async def fun2():
print(3)
await asyncio.sleep(2)
print(4)
tasks = [
asyncio.ensure_future(fun1()),
asyncio.ensure_future(fun2())
]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
- 结果:
1
3
2
4
非异步协程
下载图片示例
import requests
url_list = [
'https://www.aclas.com/uploadfile/uploadfile/225986195944098.png',
'https://www.aclas.com/uploadfile/uploadfile/26507715014500.jpg',
'https://www.aclas.com/uploadfile/uploadfile/34698673154118.jpg',
]
def download_image(url):
filename = url.rsplit('/')[-1]
res = requests.get(url)
with open(filename, 'wb') as file:
file.write(res.content)
print(filename + '下载完成')
if __name__ == '__main__':
for url in url_list:
download_image(url)
异步协程
下载图片示例
import aiohttp
import asyncio
url_list = [
'https://www.aclas.com/uploadfile/uploadfile/225986195944098.png',
'https://www.aclas.com/uploadfile/uploadfile/26507715014500.jpg',
'https://www.aclas.com/uploadfile/uploadfile/34698673154118.jpg',
]
# 下载图片
async def download_image(request,url):
print('开始发送请求',url)
async with request.get(url,verify_ssl=False) as res:
content = await res.content.read()
filename = url.rsplit('/')[-1]
with open(filename, 'wb') as file:
file.write(content)
print(filename + '下载完成')
# 创建请求对象并创建任务,等待任务执行完成
async def main():
async with aiohttp.ClientSession() as request:
tasks = [asyncio.create_task(download_image(request,url)) for url in url_list]
await asyncio.wait(tasks)
if __name__ == '__main__':
# asyncio.run(main()) 这种写法会报错...
loop = asyncio.get_event_loop() # 创建'轮询对象'并开始执行
loop.run_until_complete(main())
标签:异步,fun1,fun2,Python,编程,url,print,def,asyncio
From: https://www.cnblogs.com/qinganning/p/17547454.html