基础知识回顾——上下文管理器
上下文管理机制
很多情况,当我们使用完一个资源后,我们需要手动的关闭掉它,比如操作文件,建立数据库连接等。但是,在使用资源的过程中,如果遇到异常,很可能错误被直接抛出,导致来不及关闭资源。所以在大部分时候,我们使用”try-finally”语句来确保资源会关闭。
1 try: 2 f = open('test.txt', 'w+') 3 print(f.closed) #判断文件是否关闭 4 f.write('Hello World!') 5 finally: 6 f.close() 7 print(f.closed) #判断文件是否关闭
运行结果:
False
True
Python语言里提供的with语句功能几乎同”try-finally”一样,代码更简洁。
1 with open("test.txt", "w") as f: 2 print(f.closed) 3 f.write("Hello World!") 4 print(f.closed)
运行结果:
False
True
以上即是上下文管理器的用法,Python要求在with语句进入时自动调用__enter__()方法,其返回值会赋给as关键字后的变量;在with语句块退出后自动调用__exit__()方法。对于文件对象f来说,它定义了__enter__()和__exit__()方法(可以通过dir(f)看到)。在f的__exit__()方法中,有self.close()语句,这样就不用明文写f.close()了。
自定义上下文管理器
要自定义类似with语句的类,其内部必须提供两个内置方法__enter__以及__exit__。前者在主体代码执行前执行,后则在主体代码执行后执行。__enter__()返回的一对象作为as所指的变量。
1 class ContextManagerDemo(object): 2 def __init__(self,text): 3 self.text = text 4 5 def __enter__(self): 6 self.text = "I say: " + self.text 7 #print self <__main__.ContextManagerDemo object at 0x023557D0> 8 return self 9 10 def __exit__(self, exc_type, exc_val, exc_tb): 11 self.text = self.text + "!" 12 #参数exc_type, exc_val, exc_tb分别代表异常类型,异常值,和异常的Traceback。当处理完异常后,可以让”__exit__()”方法返回True,此时该异常就不会再被抛出。正常程序中三个参数都是None 13 14 with ContextManagerDemo('hello') as f: #上下文管理器会使用__enter__()返回的这一对象作为as所指的变量f,如果没有返回对象,text属性则无法调用 15 print f.text 16 17 print f.text
运行结果:
1 I say: hello 2 I say: hello!
上下文管理器应用
1.管理多个文件
1 with open('data.txt') as source, open('target.txt', 'w') as target: 2 target.write(source.read())
2.管理数据库游标
1 import pymysql 2 3 def get_conn(**kwargs): 4 return pymysql.connect(host=kwargs.get('host', 'localhost'),
port=kwargs.get('port', 8080),
user=kwargs.get('user'),
passwd=kwargs.get('passwd')) 5 6 def main(): 7 conn = get_conn(user='Admin', passwd='123456') 8 with conn as cur: 9 cur.execute('show databases') 10 print cur.fetchall() 11 12 if __name__ == '__main__': 13 main()