Nesting Python context managers

后端 未结 2 727
情歌与酒
情歌与酒 2020-12-10 16:14

In this question, I defined a context manager that contains a context manager. What is the easiest correct way to accomplish this nesting? I ended up calling self.te

2条回答
  •  离开以前
    2020-12-10 16:19

    contextlib.contextmanager works great for functions, but when I need a classes as context manager, I'm using the following util:

    class ContextManager(metaclass=abc.ABCMeta):
      """Class which can be used as `contextmanager`."""
    
      def __init__(self, filename):
        self.filename = filename
    
      def __init__(self):
        self.__cm = None
    
      @abc.abstractmethod
      @contextlib.contextmanager
      def contextmanager(self):
        raise NotImplementedError('Abstract method')
    
      def __enter__(self):
        self.__cm = self.contextmanager()
        return self.__cm.__enter__()
    
      def __exit__(self, exc_type, exc_value, traceback):
        return self.__cm.__exit__(exc_type, exc_value, traceback)
    

    This allow to declare contextmanager classes with the generator syntax from @contextlib.contextmanager. It makes it much more natural to nest contextmanager, without having to manually call __enter__ and __exit__. Example:

    class MyClass(ContextManager):
    
      def __init__(self, filename):
        self._filename = filename
    
      @contextlib.contextmanager
      def contextmanager(self):
        with tempfile.TemporaryFile() as temp_file:
          yield temp_file
          ...  # Post-processing you previously had in __exit__
    
    
    with MyClass('filename') as x:
      print(x)
    

    I wish this was in the standard library...

提交回复
热议问题