面试题答案
一键面试1. 资源管理与 try - except - finally
结构
在Python的异步编程中,当使用asyncio
库处理网络请求资源并涉及资源获取与释放时,可以按照以下方式合理使用try - except - finally
结构:
import asyncio
async def fetch_data():
# 模拟资源获取,这里假设是一个网络连接
resource = None
try:
# 模拟异步网络请求获取网页内容
await asyncio.sleep(1)
resource = "模拟获取到的网页内容"
print("资源获取成功")
return resource
except Exception as e:
print(f"获取资源时发生错误: {e}")
finally:
if resource:
# 模拟资源释放
print("资源释放")
async def main():
result = await fetch_data()
print(f"最终结果: {result}")
if __name__ == "__main__":
asyncio.run(main())
在上述代码中,fetch_data
函数模拟了一个异步网络请求资源获取的过程。在try
块中执行资源获取的异步操作。如果发生异常,在except
块中捕获并处理。无论是否发生异常,finally
块都会执行,用于释放获取到的资源。
2. 异步操作并发特性下的特殊情况
- 并发资源竞争:在并发场景下,多个异步任务可能同时尝试获取或释放同一个资源,这可能导致资源竞争问题。例如,多个任务同时尝试关闭同一个网络连接。为了避免这种情况,可以使用锁(
asyncio.Lock
)来确保同一时间只有一个任务可以访问或操作资源。 - 异常处理一致性:当多个异步任务并发执行时,如果其中一个任务发生异常,需要确保整个应用程序的状态是一致的。例如,如果一个任务在获取资源后发生异常,但没有正确释放资源,可能会导致其他依赖该资源的任务失败。所以在每个异步任务中都要正确处理异常并释放资源。
- 任务取消:在并发环境中,可能会出现任务被取消的情况。当一个异步任务被取消时,同样需要确保资源被正确释放。可以通过在
try - except
结构中捕获asyncio.CancelledError
异常来处理任务取消的情况,并在finally
块中进行资源释放。例如:
import asyncio
async def fetch_data():
resource = None
try:
await asyncio.sleep(1)
resource = "模拟获取到的网页内容"
print("资源获取成功")
await asyncio.sleep(10) # 模拟长时间运行任务,可被取消
return resource
except asyncio.CancelledError:
print("任务被取消")
finally:
if resource:
print("资源释放")
async def main():
task = asyncio.create_task(fetch_data())
await asyncio.sleep(2)
task.cancel()
try:
await task
except asyncio.CancelledError:
pass
if __name__ == "__main__":
asyncio.run(main())
在这个示例中,fetch_data
任务在运行一段时间后被取消,asyncio.CancelledError
异常被捕获,确保资源在任务取消时也能正确释放。