Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python yield with no argument in try block

Tags:

python

I was reading this article and it was showing this interesting bit of code:

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

Here, they are yielding with no argument in a try block. And then using it within a with block. Can someone please explain what is going on here?

like image 596
drewman Avatar asked Feb 19 '23 00:02

drewman


1 Answers

The code in the post appears to be wrong. It would make sense if the various error handlers were decorated with contextmanager. Note that, in the post, the code imports contextmanager but doesn't use it. This makes me think the person just made a mistake in creating the post and left contextmanager out of that example. (The later examples in the post do use contextmanager.) I think the code as posted will cause an AttributeError, because the various _error_handler functions aren't context managers and don't have the right __enter__ and __exit__ methods.

With contextmanager, the code makes sense based on the documentation:

At the point where the generator yields, the block nested in the with statement is executed. The generator is then resumed after the block is exited. If an unhandled exception occurs in the block, it is reraised inside the generator at the point where the yield occurred.

like image 128
BrenBarn Avatar answered Feb 20 '23 18:02

BrenBarn