title: Correct way to manage multiple resources with context managers
body: <p>I have some resources which I have wrapped in a context manager class.</p>
  
  <pre><code>class Resource:
      def __init__(self, res):
          print(f'allocating resource {res}')
          self.res = res
  
      def __enter__(self):
          return self.res
  
      def __exit__(self, typ, value, traceback):
          print(f'freed resource {self.res}')
  
      def __str__(self):
          return f'{self.res}'
  </code></pre>
  
  <p>If I were to use 2 resources directly, I could use the following syntax:</p>
  
  <pre><code>with Resource('foo') as a, Resource('bar') as b:
      print(f'doing something with resource a({a})')
      print(f'doing something with resource b({b})')
  </code></pre>
  
  <p>This works as expected:</p>
  
  <blockquote>
  <pre><code>allocating resource foo
  allocating resource bar
  doing something with resource a(foo)
  doing something with resource b(bar)
  freed resource bar
  freed resource foo
  </code></pre>
  </blockquote>
  
  <p>What I'd like to do, however, is wrap the use of these multiple resources into a class <code>Task</code>, and make that itself a context manager.</p>
  
  <p>This is my first attempt at creating such a <code>Task</code> class which manages 2 resources:</p>
  
  <pre><code>class Task:
      def __init__(self, res1, res2):
          self.a = Resource(res1)
          self.b = Resource(res2)
  
      def __enter__(self):
          return self
  
      def __exit__(self, type, value, traceback):
          self.b.__exit__(type, value, traceback)
          self.a.__exit__(type, value, traceback)
  
      def run(self):
          print(f'running task with resource {self.a} and {self.b}')
  </code></pre>
  
  <p>I can now use the familiar syntax:</p>
  
  <pre><code>with Task('foo', 'bar') as t:
      t.run()
  </code></pre>
  
  <p>And again this works as expected:</p>
  
  <blockquote>
  <pre><code>allocating resource foo
  allocating resource bar
  running task with resource foo and bar
  freed resource bar
  freed resource foo
  </code></pre>
  </blockquote>
  
  <p>This all works fine, except when an exception is thrown trying to free one of the resources.</p>
  
  <p>To illustrate I have modified my <code>Resource</code> class to throw an exception for one of the resources:</p>
  
  <pre><code>class Resource:
      def __init__(self, res):
          print(f'allocating resource {res}')
          self.res = res
  
      def __enter__(self):
          return self.res
  
      def __exit__(self, typ, value, traceback):
          print(f'try free resource {self.res}')
          if self.res == 'bar':
              raise RuntimeError(f'error freeing {self.res} resource')
          print(f'freed resource {self.res}')
  
      def __str__(self):
          return f'{self.res}'
  </code></pre>
  
  <p>With the previous manual use of 2 resources:</p>
  
  <pre><code>try:
      with Resource('foo') as a, Resource('bar') as b:
          print(f'doing something with resource a({a})')
          print(f'doing something with resource b({b})')
  except:
      pass
  </code></pre>
  
  <p>In the face of the exception freeing <code>bar</code>, <code>foo</code> is still freed:</p>
  
  <pre><code>allocating resource foo
  allocating resource bar
  doing something with resource a(foo)
  doing something with resource b(bar)
  try free resource bar
  try free resource foo
  freed resource foo
  </code></pre>
  
  <p>However, doing the same with <code>Task</code>, I leak the second resource:</p>
  
  <pre><code>try:
      with Task('foo', 'bar') as t:
          t.run()
  except:
      pass
  </code></pre>
  
  <p>Output showing I never try free <code>foo</code>:</p>
  
  <blockquote>
  <pre><code>allocating resource foo
  allocating resource bar
  running task with resource foo and bar
  try free resource bar
  </code></pre>
  </blockquote>
  
  <p><strong>Questions:</strong></p>
  
  <ul>
  <li><p>I could wrap each explicit call to <code>Resource.__exit__</code> in a <code>try</code>/<code>except</code> block, but then if I want to propagate the exception further up the call stack whilst still freeing up all the resources, I have to keep track of all exceptions and then rethrow them afterwards... it feels incorrect.</p></li>
  <li><p>It also feels "dirty" calling <code>Resource.__exit__</code> explicitly from <code>Task.__exit__</code>, rather than having the <code>with</code> statement call it implicitly for me. Is there a way to use a context manager <em>inside</em> a class like I'm trying to do? </p></li>
  </ul>
  
  <p>What is the right way to handle multiple resources inside a single context manager?</p>