你是不是这样读过文件
with open("file","r") as f_reader:
content = f_reader.readlines()
为什么你要用"with"呢,因为在这段读取文件代码结束后,会自动执行close()
with是一个神奇的关键字,它可以在代码中开辟一段由它管理的上下文,并控制程序在进入和退出这段上下文时的行为,即进入时打开文件,并返回文件对像,退出时关闭文件对像
并不是只有文件才能用上下文管理器,只要满足上下文管理器协议都可以
上下文管理器定义了“进入”和“退出”动作的特殊对像,要创建一个上下文管理器,只要实现__enter__和__exit__两处魔法方法
我们再举个例子
class SayHelloTo:
def __init__(self,name):
self.name = name
def __enter__(self):
# __enter__在进入管理器时被调用,返回结果通过as关键字获取,传给as后面的变量
return f"say hello to {self.name}"
def __exit__(self, exc_type, exc_val, exc_tb):
#__exit__ 会在执行结束后调用
print("exit")
return False
with SayHelloTo("monkey") as s:
print(s)
输出:
say hello to monkey
exit
使用@contextmanager装饰器,在contextmanager模块下
from contextlib import contextmanager
@contextmanager
def say_hello_to(person_name):
result = f"say hello to {person_name}"
#yield之前表示—__enter__内容,yield后面表示__exit__内容,yield后面的变量你可以
#理解成__enter__的返回值
yield result
print("exit")
with say_hello_to("leilei") as s:
print(s)
def __exit__(self, exc_type, exc_val, exc_tb):
#__exit__ 会在执行结束后调用
print("exit")
return Falseexit后面的参数是什么,return Flase是干啥,那可不可以return True呢
这就要说上下文管理器另一种常用方式,忽略某些不必要的异常
其实我也没想出来哪些异常不必要,那我们就举个不恰当的例子,比如说
json.loads('{"123":{134}}')明眼人一看出来。就会报:json.decoder.JSONDecodeError 异常
那我怎样忽略异常呢:
import json
class IgnoreJsonException:
def __enter__(self):
pass
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type == json.decoder.JSONDecodeError :
return True
return False
with IgnoreJsonException():
json.loads('{"123":{134}}') #运行结果没有报任何异常
1、exc_type:异常类型
2、 exc_val:异常对像,如果在上面的例子,他的值是“Expecting property name enclosed in double quotes: line 1 column 9 (char 8)”
3、exc_tb:错误的堆栈对像
当然如果没有异常的情况下,上面三个参数值都是None
返回True:这个异常会被当前的with语音压制住,不会报出
返回Flase:那这个异常就会正常抛出,交由调用方处理
我换个输入
class IgnoreJsonException:
def __enter__(self):
pass
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type == json.decoder.JSONDecodeError :
return True
return False
with IgnoreJsonException():
#我现在传入的是none,则他抛出的不是json.decoder.JSONDecodeError异常,所以
#走了return False的分支,异常会原封不动的被抛出
json.loads(None)
运行结果:
Traceback (most recent call last):
File "D:/practice_code/Practice/exception_demo/demo05.py", line 20, in
json.loads(None)
File "D:\work_tools\python\lib\json\__init__.py", line 341, in loads
raise TypeError(f'the JSON object must be str, bytes or bytearray, '
TypeError: the JSON object must be str, bytes or bytearray, not NoneType
import json
from contextlib import suppress
with suppress(json.decoder.JSONDecodeError):
json.loads('{"123":{134}}')