В Python 2.7 и 3.1 и выше вы можете написать:
with A() as X, B() as Y, C() as Z:
do_something()
Обычно это лучший метод для использования, но если у вас есть список менеджеров контекста неизвестной длины, он вам понадобится из нижеприведенных методов.
В Python 3.3 вы можете ввести список менеджеров контекста неизвестной длины с помощью contextlib.ExitStack :
with ExitStack() as stack:
for mgr in ctx_managers:
stack.enter_context(mgr)
# ...
Это позволяет вам создавать менеджеры контекста, как вы добавление их в ExitStack
, что предотвращает возможную проблему с contextlib.nested
(упоминается ниже).
contextlib2 предоставляет резервный порт ExitStack
для Python 2.6 и 2.7.
В Python 2.6 и ниже вы можете использовать contextlib.nested
:
from contextlib import nested
with nested(A(), B(), C()) as (X, Y, Z):
do_something()
эквивалентно:
m1, m2, m3 = A(), B(), C()
with m1 as X:
with m2 as Y:
with m3 as Z:
do_something()
Обратите внимание, что это не совсем то же самое, что обычно используется вложенные с
, потому что A ()
, B ()
и C ()
будут вызываться изначально, перед входом в контекст менеджеры. Это не будет работать правильно, если одна из этих функций вызовет исключение.
contextlib.nested
устарел в новых версиях Python в пользу вышеуказанных методов.
Первая часть вашего вопроса возможна в Python 3.1 .
С более чем одним элементом диспетчеры контекста обрабатываются так, как если бы несколько операторов with были вложены:
с A () как a, B () как b: сюита
эквивалентно
с A () как a: с B () как b: сюита
Изменено в версии 3.1 : Поддержка множественных контекстных выражений