python--上下文管理器
在python中我们打开文件有两种方式,一种是使用open直接打开,还有一种通过with来打开文件
今天自我总结下with打开文件的原理
首先我们明白通过with打开文件后是不需要我们手动去关闭的,但是为什么不需要手动关闭呢?
原因大概是因为在代码底层里面实现了自动关闭的吧
接下来我们分析下原理,首先看以下代码
class B: def __enter__(self): print("正在执行enter方法") def __exit__(self, exc_type, exc_val, exc_tb): print("正在执行exit方法") with B() as f: print(f)
那么我们直接运行此脚本看看结果:
正在执行enter方法
None
正在执行exit方法
忽略中间那个None(因为没有return),我们看到直接使用with B() ...的话打印的结果是先执行__enter__方法,然后执行__exit__方法
看到这里了你是不是有什么想法?
1、可以将打开文件以及操作放在__enter__中
2、将关闭文件的操作放在__exit__中
那么我们来实现下
1、将文件打开的操作放在__enter__中,发现需要文件名,这可咋整?
发现在with B()中其实也是要传递文件名以及打开方式等等参数,那么就明白了,参数可以通过__init__方法来传递
class B: def __init__(self, file_name, mode, encoding="utf-8"): self.file_name = file_name self.mode = mode self.encoding = encoding def __enter__(self): print("正在执行enter方法") f = open(self.file_name, self.mode, encoding=self.encoding) return f def __exit__(self, exc_type, exc_val, exc_tb): print("正在执行exit方法")
以上在__enter__中已经实现了打开文件的操作并返回
2、接下来就是在__exit__中实现关闭文件的操作了
1 class B: 2 def __init__(self, file_name, mode, encoding="utf-8"): 3 self.file_name = file_name 4 self.mode = mode 5 self.encoding = encoding 6 7 def __enter__(self): 8 print("正在执行enter方法") 9 self.f = open(self.file_name, self.mode, encoding=self.encoding) 10 return self.f 11 12 def __exit__(self, exc_type, exc_val, exc_tb): 13 print("正在执行exit方法") 14 self.f.close()
那么我们接下来执行下,目前我这个文件已经存在内容了,我们来读取下
with B("b.txt", "r") as f: print(f.read())
执行结果:
1 正在执行enter方法 2 ceshi cehsi 3 正在执行exit方法
结果很完美,打开文件,然后读取,最后关闭
至于python上下文管理器可以干嘛?我觉得做自动化测试里面也可以用到,比如自动化中连接数据库的代码
class DB: """ 上下文管理器实现连接MySQL """ def __init__(self, host,port,user,password,charset,database): self.conn = pymysql.connect(host=host, port=port, user=user, password=password, charset=charset, database=database) self.cursor = self.conn.cursor() def __enter__(self): return self.cursor def __exit__(self, exc_type, exc_val, exc_tb): self.cursor.close() self.conn.close()
上面也就是本人对python中上下文管理器的一点认识,请大家批评指正!