我正在阅读这篇文章,它展示了这段有趣的代码:
class Car(object):
def _factory_error_handler(self):
try:
yield
except FactoryColorError, err:
stacktrace = sys.exc_info()[2]
raise ValidationError(err.message), None, stacktrace
def _create_customizer_error_handler(self, vin):
try:
yield
except CustomizerError, err:
self._factory.remove_car(vin)
stacktrace = sys.exc_info()[2]
raise ValidationError(err.message), None, stacktrace
def _update_customizer_error_handler(self, vin):
try:
yield
except CustomizerError, err:
stacktrace = sys.exc_info()[2]
raise ValidationError(err.message), None, stacktrace
def create(self, color, stereo):
with self._factory_error_handler():
vin = self._factory.make_car(color)
with self._create_customizer_error_handler(vin):
self._customizer.update_car(vin, stereo)
return vin
def update(self, vin, color, stereo):
with self._factory_error_handler():
self._factory.update_car_color(vin, color)
with self._update_customizer_error_handler(vin):
self._customizer.update_car(vin, stereo)
return
Run Code Online (Sandbox Code Playgroud)
在这里,他们在一个try区块中没有任何争论而屈服.然后在一个with块内使用它.有人可以解释一下这里发生了什么吗?
帖子中的代码似乎是错误的.如果各种错误处理程序都被装饰,那将是有意义的contextmanager.请注意,在帖子中,代码导入contextmanager但不使用它.这让我觉得这个人在创建帖子时犯了一个错误而离开contextmanager了那个例子.(帖子中后面的例子确实可以使用contextmanager.)我认为发布的代码会导致AttributeError,因为各种_error_handler函数不是上下文管理器,没有权利__enter__和__exit__方法.
有了contextmanager,代码根据文档有意义:
在生成器生成的点处,执行嵌套在with语句中的块.然后在退出块之后恢复发生器.如果块中发生未处理的异常,则在生成器发生的点处将其重新加入.