Créer un « avec » bloc sur plusieurs gestionnaires de contexte? [dupliquer]
-
26-09-2019 - |
Question
Cette question a déjà une réponse ici:
Supposons que vous avez trois objets que vous acquérez via le gestionnaire de contexte, par exemple verrouillage A, une connexion db et un socket IP. Vous pouvez les acquérir par:
with lock:
with db_con:
with socket:
#do stuff
Mais est-il un moyen de le faire dans un bloc? quelque chose comme
with lock,db_con,socket:
#do stuff
En outre, il est possible, étant donné un tableau de longueur inconnue des objets qui ont des gestionnaires de contexte, est-il possible de faire en quelque sorte:
a=[lock1, lock2, lock3, db_con1, socket, db_con2]
with a as res:
#now all objects in array are acquired
Si la réponse est, est-il « non » parce que la nécessité d'une fonction d'une telle implique une mauvaise conception, ou peut-être je devrais suggérer dans un pep? :-P
La solution
Python 2.7 et 3.1 et au-dessus , vous pouvez écrire:
with A() as X, B() as Y, C() as Z:
do_something()
Ceci est normalement la meilleure méthode à utiliser, mais si vous avez une liste de longueur inconnue des gestionnaires de contexte vous aurez besoin l'une des méthodes ci-dessous.
Python 3.3 , vous pouvez entrer une liste de longueur inconnue des gestionnaires de contexte à l'aide contextlib.ExitStack :
with ExitStack() as stack:
for mgr in ctx_managers:
stack.enter_context(mgr)
# ...
Cela vous permet de créer les gestionnaires de contexte que vous les ajoutez à la ExitStack
, ce qui empêche le problème possible avec contextlib.nested
(mentionné ci-dessous).
contextlib2 fournit un rétroportage ExitStack
pour Python 2.6 et 2.7.
Autres conseils
La première partie de votre question est possible dans Python 3.1 .
Avec plus d'un élément, sont traités comme si multiples avec des déclarations ont été imbriquées les gestionnaires de contexte:
with A() as a, B() as b: suite
est équivalent à
with A() as a: with B() as b: suite
Changement dans la version 3.1 : Prise en charge de multiples expressions de contexte
@ interjay est correcte. Toutefois, si vous devez le faire pour les gestionnaires de contexte à long, par exemple les gestionnaires de contexte de mock.patch, alors vous rendrez vite compte que vous voulez briser ce à travers les lignes. Il se trouve que vous ne pouvez pas les envelopper dans parens, de sorte que vous devez utiliser des barres obliques inverses. Voici ce qui ressemble à:
with mock.patch('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') as a, \
mock.patch('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb') as b, \
mock.patch('cccccccccccccccccccccccccccccccccccccccccc') as c:
do_something()
La deuxième partie de votre question est résolue avec contextlib.ExitStack
Python 3.3 .
À la suite de @ réponse de sage88 vous pouvez toujours attribuer ces patchs ont des noms de variables significatives avant d'entrer en eux.
Vous pouvez créer ces patches dans plusieurs lignes
a_patch = mock.patch('aaaaaaa')
b_patch = mock.patch('bbbbbbb')
c_patch = mock.patch('ccccccc')
with a_patch as a, b_patch as b, as c:
do_something()