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 .