Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chain dynamic iterable of context managers to a single with statement

I have a bunch of context managers that I want to chain. On the first glance, contextlib.nested looked like a fitting solution. However, this method is flagged as deprecated in the documentation which also states that the latest with statement allows this directly:

Deprecated since version 2.7: The with-statement now supports this functionality directly (without the confusing error prone quirks).

However I could not get Python 3.4.3 to use a dynamic iterable of context managers:

class Foo():
    def __enter__(self):
        print('entering:', self.name)
        return self
    def __exit__(self, *_):
        pass
    def __init__(self, name):
        self.name = name

foo = Foo('foo')
bar = Foo('bar')

whether chaining:

from itertools import chain
m = chain([foo], [bar])
with m:
     pass

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: __exit__
m = [foo, bar]

providing the list directly:

with m:
     pass

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: __exit__

or unpacking:

with (*m):
    pass

  File "<stdin>", line 1
SyntaxError: can use starred expression only as assignment target

So, how do I properly chain a dynamic amount of context managers in a with statement correctly?

like image 884
Richard Neumann Avatar asked Jun 22 '15 13:06

Richard Neumann


People also ask

What is the context manager statement in Python?

A context manager usually takes care of setting up some resource, e.g. opening a connection, and automatically handles the clean up when we are done with it. Probably, the most common use case is opening a file. with open('/path/to/file.txt', 'r') as f: for line in f: print(line)

What does the Python with statement do?

What Is the With Statement in Python? In Python, the with statement replaces a try-catch block with a concise shorthand. More importantly, it ensures closing resources right after processing them. A common example of using the with statement is reading or writing to a file.

Which of the following keywords is used to enable a context manager in Python?

Python provides an easy way to manage resources: Context Managers. The with keyword is used. When it gets evaluated it should result in an object that performs context management.

Which of the following module helps in creating a context manager using decorator context manager?

contextmanager() uses ContextDecorator so the context managers it creates can be used as decorators as well as in with statements.


1 Answers

You misunderstood that line. The with statement takes more than one context manager, separated by commas, but not an iterable:

with foo, bar:

works.

Use a contextlib.ExitStack() object if you need to support a dynamic set of context managers:

from contextlib import ExitStack

with ExitStack() as stack:
    for cm in (foo, bar):
        stack.enter_context(cm)
like image 83
Martijn Pieters Avatar answered Sep 30 '22 07:09

Martijn Pieters