在context manager中,必须要介绍两个概念:
with as... , 和 enter , exit.
下文将先介绍with语句,然后介绍 enter__和__exit, 最后介绍context manager.
- with语句的作用
它的好处是自动运行try finally语句,从而不需要人工去处理异常。
示例:
with open('some_file', 'w') as opened_file:
opened_file.write('Hola!')
等同于:
file = open('some_file', 'w')
try:
file.write('Hola!')
finally:
file.close()
首先我们自己实现一个一般情况下的context manager。
class File(object):
def __init__(self, file_name, method):
self.file_obj = open(file_name, method)
def __enter__(self):
return self.file_obj
def __exit__(self, exc_type, exc_value, traceback):
# 三个参数是在运行过程中能引起异常的情况。 当context能够正常退出时,是哪个参数都为None.
self.file_obj.close()
当运行with语句时
with File('demo.txt', 'w') as opened_file:
opened_file.write('Hola!')
运行过程:
1、先运行 __init__
生成文件句柄 opened_file
。
2. __enter__
方法打开文件并且返回文件对象。
3. 将文件对象传递给句柄opened_file
4. 写文件调用.write()
5. with语句调用后__exit__
,关闭这个文件。
tips:
可以补充代码在__enter__
和__exit————
中,这样在对文件操作的开始和退出时进行相应的动作。
另一种context manager的使用方式
使用contextlib
模块。它将contextmanager当作decorator和generator使用。不需要自己构造类,写__enter__
和__exit__
函数。
示例代码:
from contextlib import contextmanager
@contextmanager
def open_file(name):
f = open(name, 'w')
yield f
f.close()
with open_file('some_file') as f:
f.write('hola!')
open_file()是一个generator,
同时他作为decorator-- contextmanager的参数。
当我们运行with语句时,contextmanager会自动运行__enter__
和__exit__
.
同时写入文件是通过genarator来实现的。