with manager español context python with-statement contextmanager

manager - python: crea un bloque "con" en varios gestores de contexto



with python español (4)

Supongamos que tiene tres objetos que adquiere a través del administrador de contexto, por ejemplo, un bloqueo, una conexión db y un socket ip. Puedes adquirirlos por:

with lock: with db_con: with socket: #do stuff

¿Pero hay una manera de hacerlo en un bloque? algo como

with lock,db_con,socket: #do stuff

Además, ¿es posible, dada una variedad de longitud desconocida de objetos que tienen administradores de contexto, es posible hacer de alguna manera:

a=[lock1, lock2, lock3, db_con1, socket, db_con2] with a as res: #now all objects in array are acquired

Si la respuesta es "no", ¿es porque la necesidad de dicha característica implica un mal diseño, o tal vez debería sugerirlo en un pep? :-PAG


En Python 2.6 y contextlib.nested posteriores , puede usar contextlib.nested :

from contextlib import nested with nested(A(), B(), C()) as (X, Y, Z): do_something()

es equivalente a:

m1, m2, m3 = A(), B(), C() with m1 as X: with m2 as Y: with m3 as Z: do_something()

Tenga en cuenta que esto no es exactamente lo mismo que usar normalmente anidado with , porque A() , B() y C() se llamarán inicialmente, antes de ingresar a los administradores de contexto. Esto no funcionará correctamente si una de estas funciones puede generar excepciones, pero funcionará para los ejemplos en la pregunta.

En Python 2.7 y 3.1 , se ha agregado la sintaxis para esto y contextlib.nested ha quedado en desuso:

with A() as X, B() as Y, C() as Z: do_something()

En Python 3.3 , también puede ingresar una lista de longitud desconocida de gestores de contexto utilizando contextlib.ExitStack :

with ExitStack() as stack: for mgr in ctx_managers: stack.enter_context(mgr) # ...

Esto le permite crear los administradores de contexto a medida que los agrega a ExitStack , lo que evita el posible problema con contextlib.nested .

contextlib2 proporciona un ExitStack de ExitStack para Python 2.6 y 2.7.


La primera parte de su pregunta es posible en Python 3.1 .

Con más de un elemento, los administradores de contexto se procesan como si se anidaran múltiples con instrucciones:

with A() as a, B() as b: suite

es equivalente a

with A() as a: with B() as b: suite

Modificado en la versión 3.1 : Soporte para múltiples expresiones de contexto


La respuesta de @interjay es correcta. Sin embargo, si necesita hacer esto para administradores de contexto largos, por ejemplo administradores de contexto de mock.patch, entonces se da cuenta rápidamente de que desea dividir esto entre líneas. Resulta que no puedes envolverlos en paréntesis, por lo que debes usar barras diagonales inversas. Esto es lo que parece:

with mock.patch(''aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'') as a, / mock.patch(''bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'') as b, / mock.patch(''cccccccccccccccccccccccccccccccccccccccccc'') as c: do_something()


La segunda parte de su pregunta se resuelve con contextlib.ExitStack en Python 3.3 .