Python - 上下文管理器协议
- with 语句的目的是简化try/finally ,即便由于异常,return,sys.exit()调用而终止,也会执行指定的操作
- 上下文管理器协议包含__enter__和__exit__ 两个方法
- with 语句开始执行时会在上下文管理器对象上调用__enter__方法
- with 语句运行结构后会在上下文管理器对象上调用__exit__方法,以此扮演finally子句的角色
示例:
import pymysql.cursors
# Connect to the database
connection = pymysql.connect(host='localhost',
user='user',
password='passwd',
database='db',
cursorclass=pymysql.cursors.DictCursor)
with connection:
with connection.cursor() as cursor:
# Create a new record
sql = "INSERT INTO `users` (`email`, `password`) VALUES (%s, %s)"
cursor.execute(sql, ('webmaster@python.org', 'very-secret'))
# connection is not autocommit by default. So you must commit to save
# your changes.
connection.commit()
with connection.cursor() as cursor:
# Read a single record
sql = "SELECT `id`, `password` FROM `users` WHERE `email`=%s"
cursor.execute(sql, ('webmaster@python.org',))
result = cursor.fetchone()
print(result)
connection 对象实现了上下文管理器协议:
cursor 对象也实现了上下文管理器协议:
最常见的例子是确保关闭文件对象
>>> with open('package-lock.json') as fp:
... src = fp.read(60)
...
>>> len(src)
60
>>> fp # fp 绑定打开的文件,因为文件的__enter__方法返回self
<_io.TextIOWrapper name='package-lock.json' mode='r' encoding='cp936'>
>>> fp.closed,fp.encoding # 可以读取fp对象的属性
(True, 'cp936')
>>> fp.read(60) # 但是不能使用fp继续读取文本,因为在with块的末尾,Python 调用TextIOWrapper.__exit__方法把文件关闭了
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: I/O operation on closed file.
>>>
with open('package-lock.json') as fp: 求解 with 后面表达式得到的结果是上下文管理器对象。不过绑定到目标变量(在as子句中)上的值 是在上下文管理器对象上调用__enter__ 方法返回的结果
碰巧,open()函数返回一个TextIOWrapper 实例,而该实例的__enter__方法返回self。不过,其他类的__enter__方法可能会返回其他对象,而不返回上下文管理器实例
不管控制流以哪种方式退出with块,都在上下文管理器对象上调用__exit__方法,而不是在__enter__方法返回的对象上调用
with 语句的as子句是可选的。对open函数来说,必须加上as子句,以便获取文件的引用,在引用上调用方法。不过,有些上下文管理器返回None,因为没有什么有用的对象能提供给用户
import sys
class LookingGlass:
def __enter__(self):
self.original_write = sys.stdout.write
sys.stdout.write = self.reverse_write
return 'JABBERWOCKY'
def reverse_write(self,text):
self.original_write(text[::-1])
def __exit__(self, exc_type, exc_val, traceback):
sys.stdout.write = self.original_write
if exc_type is ZeroDivisionError:
print('Please DO NOT divide by zero!')
return True
if __name__ == '__main__':
with LookingGlass() as what: # 1
print('Alice,Kitty and Snowdrop') # 2
print(what)
print(what) # 3
print('Back to normal!') # 4
# out:
'''
pordwonS dna yttiK,ecilA
YKCOWREBBAJ
JABBERWOCKY
Back to normal!
'''
1.这个上下文管理器是一个LookingGlass 实例,Pyhton 在上下文管理器上调用__enter__方法,把返回结果绑定到what上
2.打印一个字符串,然后打印what 变量的值。打印处的内容都是反向的
3.现在with块执行完毕。可以看到,__enter__方法的返回值,即存储在what 变量中的值,是字符串'JABBERWOCKY'.
4.输出不再是反向的了
本文来自博客园,作者:chuangzhou,转载请注明原文链接:https://www.cnblogs.com/czzz/p/16864451.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!