python asyncio协程、Task、回调函数(done_callback)、以及functools.partial的用法
·
一、代码结构
import asyncio, time
from functools import partial # 偏函数
async def get_html():
print('get html start')
await asyncio.sleep(1)
return 'hello'
def func(f, url):
print('send email to cat..')
if __name__ == '__main__':
loop = asyncio.get_event_loop()
task = loop.create_task(get_html())
task.add_done_callback(partial)
loop.run_until_complete(task)
二、关键知识点
1. Task 和 add_done_callback
Task是 asyncio 中包装协程的对象,表示一个正在执行或即将执行的异步操作。add_done_callback(callback):当 Task 执行完毕(无论成功还是异常),会自动调用 callback,并把 Task 本身作为第一个参数传递给 callback。
2. functools.partial
partial(func, *args, **kwargs):返回一个新的函数,把 func 的部分参数提前“冻结”。- 常用于回调场景,给回调函数预先绑定一些参数。
三、逐行详细解释
1. 导入模块
import asyncio, time
from functools import partial # 偏函数
- 导入异步IO、时间模块和偏函数工具。
2. 定义协程
async def get_html():
print('get html start')
await asyncio.sleep(1)
return 'hello'
async def get_html():定义一个协程函数。print('get html start'):输出开始信息。await asyncio.sleep(1):异步延时1秒。return 'hello':返回字符串'hello'。
3. 定义回调函数
def func(f, url):
print('send email to cat..')
- 普通函数,参数
f(通常是 Future/Task),url是额外参数。 - 这里只是简单打印一行信息。
4. 主程序入口
if __name__ == '__main__':
loop = asyncio.get_event_loop()
task = loop.create_task(get_html())
task.add_done_callback(partial)
loop.run_until_complete(task)
loop = asyncio.get_event_loop():获取事件循环对象。task = loop.create_task(get_html()):调度协程,返回 Task 对象。task.add_done_callback(partial):- 这里有错误!
partial是 functools.partial 这个类本身,不是一个回调函数。- 正确用法应该是:
task.add_done_callback(partial(func, url='http://example.com')) - 这样,func 会在 task 完成后被调用,参数为 (task, url)。
loop.run_until_complete(task):运行事件循环,直到 task 完成。
四、正确用法示例
1. 正确绑定回调
if __name__ == '__main__':
loop = asyncio.get_event_loop()
task = loop.create_task(get_html())
# partial(func, url) 生成一个新函数,等价于 lambda f: func(f, url)
task.add_done_callback(partial(func, url='http://example.com'))
loop.run_until_complete(task)
2. 回调函数的执行
- 当
get_html()协程执行完毕,task 完成,事件循环会自动调用func(task, url)。 - 你可以在回调里通过
task.result()获取协程的返回值。
def func(f, url):
print('send email to cat..')
print('url:', url)
print('协程返回值:', f.result())
五、完整示例
import asyncio
from functools import partial
async def get_html():
print('get html start')
await asyncio.sleep(1)
return 'hello'
def func(f, url):
print('send email to cat..')
print('url:', url)
print('协程返回值:', f.result())
if __name__ == '__main__':
loop = asyncio.get_event_loop()
task = loop.create_task(get_html())
task.add_done_callback(partial(func, url='http://example.com'))
loop.run_until_complete(task)
输出:
get html start
send email to cat..
url: http://example.com
协程返回值: hello
六、核心原理总结
- add_done_callback 用于在 Task 完成后自动执行回调,常用于通知、日志、后处理等场景。
- partial 可以为回调函数预先绑定参数,简化回调签名。
- 回调函数的第一个参数永远是 Task/Future 本身,可以通过
.result()获取协程的返回值。
更多推荐



所有评论(0)