Python异常处理

传统异常处理

在Python中,传统的异常处理格式如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
try:
    f = open('foo.txt')
    print("No error occurs!")
except FileExistsError: # 按照不同的异常类型捕获异常
	print('There is a FileExistsError!')
except FileNotFoundError:
	print('There is a FileNotFoundError!')
else:
    print(f.readlines()) # 当未触发异常时,将会执行else中的语句
finally:
    print("Operations are Finished!") # finally定义无论在任何情况下都会执行的清理行为

结果1:

1
2
There is a FileNotFoundError!
Operations are Finished!

结果2:

1
2
3
No error occurs!
['Hello World!']
Operations are Finished!

With

with语句可以极大地简化这种try-except-else-finally模式。例如,如果我们想要实现文件的安全读写,传统的写法是这样的:

1
2
3
4
5
file = open('foo.txt', 'w+')
try:
    file.write('hello world !')
finally:
    file.close()

而使用with语句后是这样的:

1
2
with open('foo.txt', 'w+') as file:
    file.write('hello world !')

要想使用with语句,我们需要实现一个上下文管理器类(contextmanager)。上下文管理器中含有__enter____exit__两个方法。with语句开始运行时,会在上下文管理器对象上调用__enter__方法。with语句运行结束后,会在上下文管理器对象上调 用__exit__方法。例如,我们可以写一个简单的文件管理类:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class MessageWriter:
    def __init__(self, file_name):
        self.file_name = file_name
      
    # 解释器在调用__enter__时,除了隐式的self之外,不会传入任何参数
    def __enter__(self):
        self.file = open(self.file_name, 'w+')
        return self.file
    
    # 传给__exit__方法的三个参数列举如下:exc_type(异常类);exc_value(异常实例);traceback(traceback对象)
    def __exit__(self, exc_type, exc_value, traceback):
        self.file.close()
  
with MessageWriter('foo.txt') as f:
    f.write('a test for MessageWriter')

@contextmanager

相比于实现一个上下文管理器类,装饰器@contextmanager能减少创建上下文管理器的样板代码量,因为不用编写一个完整的类,定义__enter____exit__方法,而只需实现有一个yield语句的生成器。

在此用法中,yield语句前面的所有代码在with块开始时(即解释器调用__enter__方法时)执行,yield语句后面的代码在with块结束时(即调用__exit__方法时)执行。

使用@contextmanager重写上面的代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from contextlib import contextmanager

@contextmanager
def myopen(file_name):
    f = open(file_name,'w+')
    yield f
    f.close()

with myopen('foo.txt') as f:
    f.write('a test for contextmanager')
Licensed under CC BY-NC-SA 4.0
Built with Hugo
Theme Stack designed by Jimmy
visitors: total visits: time(s) reads: time(s)