Question

Est-il possible de déclarer plus d'une variable en utilisant une instruction with en Python?

Quelque chose comme:

from __future__ import with_statement

with open("out.txt","wt"), open("in.txt") as file_out, file_in:
    for line in file_in:
        file_out.write(line)

... ou est le nettoyage deux ressources en même temps le problème?

Était-ce utile?

La solution

Il est possible dans Python 3 depuis v3.1 et < a href = "http://docs.python.org/dev/whatsnew/2.7.html#other-language-changes" rel = "noreferrer"> Python 2.7 . Le nouveau with syntaxe prend en charge plusieurs gestionnaires de contexte:

with A() as a, B() as b, C() as c:
    doSomething(a,b,c)

Contrairement au contextlib.nested, cela garantit que a et b auront leur appelé même si __exit__() ou il est la méthode C() de __enter__() soulève une exception.

Autres conseils

contextlib.nested soutient ceci:

import contextlib

with contextlib.nested(open("out.txt","wt"), open("in.txt")) as (file_out, file_in):

   ...

Mise à jour: Pour citer la documentation concernant contextlib.nested :

  

Déconseillédepuis version 2.7 : La déclaration avec-supporte maintenant ce   fonctionnalité directement (sans l'erreur de confusion bizarreries sujets).

Voir Rafał de réponse Dowgird pour plus d'informations.

Notez que si vous divisez les variables en lignes, vous devez utiliser antislashs pour envelopper les nouvelles lignes.

with A() as a, \
     B() as b, \
     C() as c:
    doSomething(a,b,c)

Parenthèses ne fonctionnent pas, puisque Python crée un tuple à la place.

with (A(),
      B(),
      C()):
    doSomething(a,b,c)

Depuis tuples manque un attribut __enter__, vous obtenez une erreur (undescriptive et ne précise pas le type de classe):

AttributeError: __enter__

Si vous essayez d'utiliser as entre parenthèses, Python attrape l'erreur au moment de l'analyse:

with (A() as a,
      B() as b,
      C() as c):
    doSomething(a,b,c)
  

SyntaxError: syntaxe non valide

https://bugs.python.org/issue12782 semble être lié à cette question.

Je pense que vous voulez faire ceci:

from __future__ import with_statement

with open("out.txt","wt") as file_out:
    with open("in.txt") as file_in:
        for line in file_in:
            file_out.write(line)

Depuis Python 3.3, vous pouvez utiliser la ExitStack à partir du module contextlib .

Il peut gérer un dynamique nombre d'objets sensibles au contexte, ce qui signifie qu'il se révélera particulièrement utile si vous ne connaissez pas

combien de fichiers que vous allez gérer.

L'utilisation cas canonique qui est mentionné dans la documentation gère un certain nombre dynamique de fichiers.

with ExitStack() as stack:
    files = [stack.enter_context(open(fname)) for fname in filenames]
    # All opened files will automatically be closed at the end of
    # the with statement, even if attempts to open files later
    # in the list raise an exception

Voici un exemple générique:

from contextlib import ExitStack

class X:
    num = 1

    def __init__(self):
        self.num = X.num
        X.num += 1

    def __repr__(self):
        cls = type(self)
        return '{cls.__name__}{self.num}'.format(cls=cls, self=self)

    def __enter__(self):
        print('enter {!r}'.format(self))
        return self.num

    def __exit__(self, exc_type, exc_value, traceback):
        print('exit {!r}'.format(self))
        return True

xs = [X() for _ in range(3)]

with ExitStack() as stack:
    print(stack._exit_callbacks)
    nums = [stack.enter_context(x) for x in xs]
    print(stack._exit_callbacks)
print(stack._exit_callbacks)
print(nums)

Sortie:

deque([])
enter X1
enter X2
enter X3
deque([<function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f86158>, <function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f861e0>, <function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f86268>])
exit X3
exit X2
exit X1
deque([])
[1, 2, 3]
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top