4

我正在阅读这篇文章,它显示了这段有趣的代码:

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

try在这里,他们在一个块中没有参数就让步了。with然后在一个块内使用它。有人可以解释一下这里发生了什么吗?

4

1 回答 1

8

帖子中的代码似乎是错误的。如果各种错误处理程序都用contextmanager. 请注意,在帖子中,代码导入contextmanager但不使用它。这让我觉得这个人只是在创建帖子时犯了一个错误,而contextmanager没有提到那个例子。(帖子后面的例子确实使用了contextmanager。)我认为发布的代码会导致一个AttributeError,因为各种_error_handler函数不是上下文管理器并且没有权限__enter____exit__方法。

使用,代码基于文档contextmanager是有意义的:

在生成器产生的地方,嵌套在 with 语句中的块被执行。然后在退出块后恢复生成器。如果块中发生未处理的异常,它会在生成器中在产生产生的点重新引发。

于 2012-12-28T19:54:06.000 回答