• Python上下文管理和with


    Python实用教程_spiritx的博客-CSDN博客

    有一些任务,可能事先需要设置,事后做清理工作。可以通过try…except…finally来完成,如:

    1. file = open('./test.txt', 'r')
    2. try:
    3. context = file.read()
    4. print(context)
    5. except Exception as e:
    6. print(e)
    7. finally:
    8. file.close()

    上面长长的一段代码,写的很复杂麻烦。

    python使用with语句对try…except…finally进行了大幅的简化,并且使过程更容易理解。上面的过程使用with语句可以改写为:

    1. with open('./test.txt', 'r') as file:
    2. context = file.read()
    3. print(context)

    with 语句使代码更清晰、更具可读性, 它简化了文件流等公共资源的管理。在处理文件对象时使用 with 关键字是一种很好的做法。

    上下文管理器

    with 语句实现原理建立在上下文管理器之上。上下文管理器是一个实现 __enter__ 和 __exit__ 方法的类。使用 with 语句确保在嵌套块的末尾调用 __exit__ 方法。这个概念类似于 try...finally 块的使用。

    1. with open('./test.txt', 'r') as file:
    2. context = file.read()
    3. print(context)
    4. print(hasattr(file, '__enter__')) #true
    5. print(hasattr(file, '__exit__')) #true

    在文件对象中定义了 __enter__ 和 __exit__ 方法,即文件对象也实现了上下文管理器,首先调用 __enter__ 方法,然后执行 with 语句中的代码,最后调用 __exit__ 方法。 即使出现错误,也会调用 __exit__ 方法,也就是会关闭文件流。

    1. class MyWith():
    2. def __init__(self):
    3. print('MyWith.__init__')
    4. def __enter__(self):
    5. print('MyWith.__enter__')
    6. return 'enter.return'
    7. def __exit__(self, exc_type, exc_val, exc_tb):
    8. print('MyWith.__exit__')
    9. def __del__(self):
    10. print('MyWith.__del__')
    11. with MyWith() as w:
    12. print(f'...with...{w=}')
    13. print('Game Over!')
    14. ‘’'
    15. MyWith.__init__
    16. MyWith.__enter__
    17. ...with...w='enter.return'
    18. MyWith.__exit__
    19. MyWith.__del__
    20. Game Over!
    21. ‘''

    从上面的例子执行的顺序是:

    • 执行with as语句时,MyWith类的__init__()被调用后,__enter__()方法紧接着会被调用,因此首先会打印"MyWith.__init__
      MyWith.__enter__"
    • __enter__函数返回的对象w,实际是__enter__()方法的返回值,所以打印的内容是“...with...w='enter.return'”
    • 当with as语句执行完毕以后,__exit__函数会被调用,因此随后打印的是“MyWith.__exit__”
    • 最后是w被释放,打印的是析构函数输出的内容

    __exit__函数的三个参数

    注意到__exit__函数中除了self参数外,还有三个参数type, value, trace,这些参数用于处理异常情况。

    • exc_type:表示引发的异常类型,如果代码块成功执行完毕,则为None。
    • exc_val:表示引发的异常实例,如果代码块成功执行完毕,则为None。
    • exc_tb:表示引发的异常跟踪对象,如果代码块成功执行完毕,则为None。

    下面是一个示例,演示如何使用__exit__()方法来处理异常情况:

    1. class FileManager:
    2. def __init__(self, filename, mode):
    3. self.filename = filename
    4. self.mode = mode
    5. self.file = None
    6. def __enter__(self):
    7. self.file = open(self.filename, self.mode)
    8. return self.file
    9. def __exit__(self, exc_type, exc_val, exc_tb):
    10. if exc_type is not None:
    11. print(f"An error occurred: {exc_val}")
    12. self.file.close()
    13. else:
    14. self.file.close()
    15. # 使用上下文管理器打开文件
    16. with FileManager("example.txt", "r") as file:
    17. print(file.readlines())
    18. # 使用不存在的文件名打开文件
    19. with FileManager("nonexistent_file.txt", "r") as file:
    20. print(file.readlines())

    应用场景

    文件操作

    在Python中,文件操作通常是通过open函数来实现的,当打开文件之后,我们需要使用close方法来关闭文件,保证文件的完整性和安全性。但是在实际的开发过程中,往往会出现遗漏close方法的情况,这时候就可以使用with语句来自动关闭文件,避免出现问题。例如:

    1. with open('example.txt', 'r') as f:
    2. data = f.read()
    3. #处理文件内容

    数据库操作

    在Python中,数据库操作通常是通过使用DB-API来实现的,这需要我们手动打开数据库连接和关闭数据库连接,如果不小心忘记关闭数据库连接,就可能导致数据库出现问题。使用with语句可以方便地自动关闭数据库连接,避免出现问题。例如:

    1. import sqlite3
    2. with sqlite3.connect('example.db') as conn:
    3. cursor = conn.cursor()
    4. cursor.execute('SELECT * FROM example_table')
    5. data = cursor.fetchall()
    6. #处理数据

    网络编程

    在Python中,网络编程通常是通过使用socket模块来实现的,当我们创建了一个socket对象之后,需要手动关闭socket对象,否则会出现问题。使用with语句可以方便地自动关闭socket对象,避免出现问题。

    1. import socket
    2. with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    3. s.connect(('www.baidu.com', 80))
    4. s.sendall(b'GET / HTTP/1.1\r\nHost: www.baidu.com\r\nConnection: close\r\n\r\n')
    5. data = s.recv(1024)
    6. #处理数据

  • 相关阅读:
    李彦宏:程序员将不复存在! 周鸿祎回怼!网友:先把百度程序员都开除了!
    【前端知识】Three 学习日志(十二)—— WebGL渲染器设置(锯齿模糊)
    每个开发都应该懂的正则表达式
    【小尘送书-第六期】《巧用ChatGPT轻松玩转新媒体运营》AI赋能运营全流程,帮你弯道超车、轻松攀登运营之巅
    Android 跨进程通信并传输复杂数据
    安全测试 —— Jmeter 登录接口密码 - rsa加密
    Qt实现TCP调试助手 - 简述如何在Qt中实现TCP多并发
    经典算法学习之-----直接选择排序
    2023年中国位置服务(LBS)产业链及市场规模分析[图]
    6. 【图的应用1】最⼩⽣成树(Prim、kruskal)、最短路径(BFS、Dijkstra、Floyd{含有快速求解})
  • 原文地址:https://blog.csdn.net/spiritx/article/details/132782446