Python中的协程任务取消与异常处理机制
字数 500 2025-11-11 14:45:34
Python中的协程任务取消与异常处理机制
题目描述:在Python异步编程中,协程任务的取消和异常处理是重要的并发控制机制。面试官希望了解你如何正确处理任务取消请求、如何在协程中捕获和处理不同类型的异常,以及取消和异常传播的交互机制。
解题过程:
- 基本任务取消机制
import asyncio
async def long_running_task():
try:
await asyncio.sleep(10)
print("任务完成")
except asyncio.CancelledError:
print("任务被取消")
raise # 必须重新抛出
async def main():
task = asyncio.create_task(long_running_task())
await asyncio.sleep(1)
task.cancel() # 发送取消请求
try:
await task
except asyncio.CancelledError:
print("主函数确认任务已取消")
asyncio.run(main())
关键点:调用task.cancel()并不会立即终止任务,而是向任务发送CancelledError异常,任务需要在合适的位置捕获并处理。
- 复杂的资源清理场景
import asyncio
async def database_operation():
print("连接数据库")
try:
await asyncio.sleep(5) # 模拟数据库操作
return "操作结果"
finally:
print("关闭数据库连接") # 确保资源清理
async def main():
task = asyncio.create_task(database_operation())
await asyncio.sleep(1)
task.cancel()
try:
result = await task
print(f"结果: {result}")
except asyncio.CancelledError:
print("数据库操作被取消")
asyncio.run(main())
关键点:使用finally块确保无论任务是否被取消,都能正确释放资源。
- 屏蔽取消请求的场景
import asyncio
async def critical_section():
try:
# 关键代码段,不允许被取消
with asyncio.timeout(0): # 临时屏蔽取消
await asyncio.sleep(2)
except TimeoutError:
pass # 忽略超时,继续执行关键操作
print("关键操作完成")
async def main():
task = asyncio.create_task(critical_section())
await asyncio.sleep(0.5)
task.cancel()
try:
await task
except asyncio.CancelledError:
print("任务在关键段外被取消")
asyncio.run(main())
关键点:使用asyncio.shield()或超时机制可以临时保护代码段不被取消。
- 异常传播链与聚合异常
import asyncio
async def failing_task():
await asyncio.sleep(1)
raise ValueError("任务内部错误")
async def task_with_exception():
try:
await asyncio.sleep(0.5)
task = asyncio.create_task(failing_task())
return await task
except* ValueError as eg: # Python 3.11+ 异常组
for exc in eg.exceptions:
print(f"捕获异常: {exc}")
async def main():
try:
await task_with_exception()
except Exception as e:
print(f"主函数捕获: {e}")
asyncio.run(main())
关键点:Python 3.11引入异常组处理多个并发异常,了解异常在任务链中的传播路径。
- 超时与取消的交互
import asyncio
async def complex_operation():
try:
async with asyncio.timeout(3): # 外部超时
try:
await asyncio.sleep(5) # 超过超时时间
except asyncio.CancelledError:
print("内部取消点")
raise
except TimeoutError:
print("操作超时")
return "超时结果"
async def main():
task = asyncio.create_task(complex_operation())
await asyncio.sleep(1)
# 超时和取消可能竞争发生
result = await task
print(f"最终结果: {result}")
asyncio.run(main())
关键点:理解超时机制底层也是通过取消实现的,需要处理可能的竞争条件。
- 自定义取消逻辑
import asyncio
class CancellableOperation:
def __init__(self):
self._cancelled = False
async def run(self):
for i in range(10):
if self._cancelled:
return "操作被取消"
await asyncio.sleep(1)
print(f"进度: {i+1}/10")
return "操作完成"
def cancel(self):
self._cancelled = True
async def main():
operation = CancellableOperation()
task = asyncio.create_task(operation.run())
await asyncio.sleep(3)
operation.cancel() # 自定义取消逻辑
result = await task
print(f"结果: {result}")
asyncio.run(main())
关键点:实现协作式取消机制,让任务在安全点检查取消状态。
这个知识点考察的是对异步编程中错误处理和安全退出的深入理解,包括异常传播、资源清理、取消协作等关键概念。