MST
星途 面试题库

面试题:Python上下文管理器的嵌套与异常处理

编写一个Python程序,包含多个嵌套的上下文管理器,每个上下文管理器负责不同资源的管理(例如文件、网络连接、数据库连接)。要求处理好嵌套上下文管理器之间的异常传递和资源清理,确保在任何情况下所有资源都能正确释放。同时,解释清楚在嵌套结构中异常处理和资源清理的工作原理。
49.3万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试
import contextlib


@contextlib.contextmanager
def file_manager(file_path, mode):
    try:
        file = open(file_path, mode)
        yield file
    finally:
        file.close()


@contextlib.contextmanager
def network_connection_manager():
    try:
        # 这里模拟网络连接
        print("建立网络连接")
        yield "模拟网络连接对象"
    finally:
        print("关闭网络连接")


@contextlib.contextmanager
def database_connection_manager():
    try:
        # 这里模拟数据库连接
        print("建立数据库连接")
        yield "模拟数据库连接对象"
    finally:
        print("关闭数据库连接")


def main():
    file_path = "test.txt"
    with file_manager(file_path, 'w') as file, \
            network_connection_manager() as network_conn, \
            database_connection_manager() as db_conn:
        file.write("测试内容")
        # 这里模拟可能发生异常的操作
        # raise ValueError("模拟异常")


if __name__ == "__main__":
    try:
        main()
    except Exception as e:
        print(f"捕获到异常: {e}")

异常处理和资源清理原理

  1. 上下文管理器协议:Python的上下文管理器遵循__enter____exit__方法协议。当使用with语句进入上下文时,会调用__enter__方法获取资源;当离开上下文时(正常离开或因异常离开),会调用__exit__方法释放资源。
  2. 嵌套上下文管理器:在嵌套的with语句中,Python会按照从左到右的顺序依次进入每个上下文管理器,调用它们的__enter__方法获取资源。如果在某个上下文管理器内部发生异常,Python会从最内层的上下文管理器开始,依次调用它们的__exit__方法来清理资源。
  3. 异常传递:如果__exit__方法返回False(默认行为),异常会继续向外层传递;如果返回True,则表示异常已被处理,不再继续传递。在上述代码中,每个上下文管理器的__exit__方法(由contextlib.contextmanager装饰器生成)没有显式返回,默认返回False,所以异常会传递到外层try - except块中。
  4. 资源清理:无论是否发生异常,with语句结束时都会确保所有进入的上下文管理器的__exit__方法被调用,从而保证资源的正确释放。在代码中,文件、网络连接和数据库连接在离开with块时都会被关闭,即使中间发生异常。