2009-05-21 17 views
218

¿Es posible declarar más de una variable usando una instrucción with en Python?Varias variables en la instrucción 'with' de Python

Algo así como:

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) 

... o es la limpieza de dos recursos al mismo tiempo el problema?

+0

Tal como esto: con [expr1, expr2] como f: y a continuación, utilizar f [0] y f [1]. – jbasko

+0

Hubiera estado bien porque no hay necesidad de importar algo ... pero no funciona AttributeError: el objeto 'list' no tiene atributo '__exit__' – pufferfish

+0

Si python acaba de tener cierres, no necesitaría la instrucción con –

Respuesta

411

Es posible en Python 3 since v3.1 y Python 2.7. El nuevo with syntax soporta múltiples gestores de contexto:

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

A diferencia de la contextlib.nested, esto garantiza que a y b tendrán sus __exit__() 's llaman incluso si C() o no lo __enter__() método lanza una excepción.

+0

¿es posible establecer campos iguales a algo en con instrucción como en 'con open ('./ file') como arg.x = file:'? –

+3

Además, es posible: con A() como a, B (a) como b, C (a, b) como c: –

+0

clase test2: x = 1; t2 = test2() con abrir ('f2.txt') como t2.x: para l1 en t2.x.readlines(): imprimir (l1); # Charlie Parker # probado en Python 3.6 –

18

creo que quiere hacer esto en su lugar:

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) 
+2

Así es como lo hago actualmente, pero luego el anidamiento es dos veces más profundo de lo que quiero (quiero decir) que sea ... – pufferfish

+0

Creo que este es el enfoque más limpio, cualquier otro enfoque será más difícil de leer. La respuesta de Alex Martelli parece estar más cerca de lo que quieres, pero es mucho menos legible. ¿Por qué anidar es una preocupación? –

+5

No es un gran problema, hay que admitirlo, pero, por "importar esto" (también conocido como "Zen de Python"), "flat es mejor que anidado", es por eso que agregamos contextlib.nested a la biblioteca estándar. Por cierto, 3.1 podría tener una nueva sintaxis "con A() como a, B() como b:" (el parche está, sin embargo, ningún pronunciamiento de BDFL hasta el momento) para un soporte más directo (así que claramente la solución de la biblioteca no es t considerado perfecto ...pero evitar el anidamiento no deseado es definitivamente un objetivo ampliamente compartido entre los desarrolladores principales de Python). –

53

contextlib.nested apoya esta:

import contextlib 

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

    ... 

Actualización:
Para citar la documentación, en relación con contextlib.nested:

Deprecated since version 2.7: The with-statement now supports this functionality directly (without the confusing error prone quirks).

Consulte Rafał Dowgird's answer para obtener más información.

+27

Lamento decirlo, pero creo que el administrador de contexto 'anidado' es un error y nunca debe usarse. En este ejemplo, si abrir el segundo archivo genera una excepción, el primer archivo no se cerrará en absoluto, lo que destruirá por completo el objetivo de utilizar los gestores de contexto. –

+0

¿Por qué dices eso? La documentación dice que el uso anidado es equivalente a 'with' –

+0

@Rafal anidado: un vistazo al manual parece indicar que python jerarquiza correctamente las instrucciones con. El verdadero problema es si el segundo archivo arroja una excepción al cerrar. – Unknown

Cuestiones relacionadas