2010-09-04 7 views
74

¿Es esta la forma correcta de utilizar el pitón "con" declaración en combinación con un bloque try-excepto ?:usando Python "con" declaración con excepción try-bloque

try: 
    with open("file", "r") as f: 
     line = f.readline() 
except IOError: 
    <whatever> 

Si lo es, entonces considerando la vieja manera de hacer las cosas:

try: 
    f = open("file", "r") 
    line = f.readline() 
except IOError: 
    <whatever> 
finally: 
    f.close() 

Es el principal beneficio de la expresión "with" aquí que podemos deshacernos de tres líneas de código? No me parece convincente para este caso de uso (aunque entiendo que la declaración "con" tiene otros usos).

EDITAR: ¿Es idéntica la funcionalidad de los dos bloques de código anteriores?

EDIT2 EDIT2: Las primeras respuestas hablan generalmente acerca de los beneficios de usar "con", pero las que parecen tener un beneficio marginal aquí. Todos hemos estado (o deberíamos haber estado) llamando explícitamente a f.close() durante años. Supongo que un beneficio es que los codificadores descuidados se beneficiarán del uso de "con".

+0

Posible duplicado de [detectar una excepción mientras se utiliza un pitón 'con' declaración] (http://stackoverflow.com/questions/713794/catching -an-exception-while-using-a-python-with-statement) –

Respuesta

112
  1. Los dos bloques de código que dieron se no equivalente
  2. El código que ha descrito como vieja manera de hacer las cosas tiene un error grave: en caso de abrir el archivo que falla obtendrá una segunda excepción en la cláusula finally porque f no es enlazado.

El código equivalente al viejo estilo sería:

try: 
    f = open("file", "r") 
    try: 
     line = f.readline() 
    finally: 
     f.close() 
except IOError: 
    <whatever> 

Como se puede ver, la declaración with puede hacer las cosas menos propenso a errores. En las versiones más recientes de Python (2.7, 3.1), también puede combinar varias expresiones en una sola declaración with. Por ejemplo:

with open("input", "r") as inp, open("output", "w") as out: 
    out.write(inp.read()) 

Además de eso, personalmente considero que es un mal hábito detectar cualquier excepción lo antes posible. Este no es el propósito de las excepciones. Si la función IO que puede fallar es parte de una operación más complicada, en la mayoría de los casos el IOError debe abortar toda la operación y, por lo tanto, debe manejarse en un nivel externo. Utilizando las declaraciones with, puede deshacerse de todas estas declaraciones try...finally en niveles internos.

6

Si el contenido del bloque de finally están determinadas por las propiedades del objeto de archivo se abra, ¿por qué no el implementador del objeto de archivo ser el uno para escribir el bloque de finally? Eso es el beneficio de la declaración with, mucho más de lo que le ahorra tres líneas de código en este caso particular.

Y sí, la forma en que ha combinado with y try-except es casi la única manera de hacerlo, ya que los errores causados ​​excepcionales dentro de la instrucción open sí misma no puede ser atrapado dentro del bloque with.

1

creo que se equivocó acerca de "por" declaración de que sólo reduce las líneas. Realmente hace la inicialización y maneja el desmontaje.

En su caso "con" hace

  • abrir un archivo,
  • proceso de su contenido, y
  • asegúrese de cerrarla.

Aquí es vínculo de entendimiento "con" declaración: http://effbot.org/zone/python-with-statement.htm

Editar: Si su uso de "con" es correcta y la funcionalidad de los dos bloques de código es idéntico. Pregunta sobre por qué usar "con"? es por los beneficios que obtienes con eso. como mencionaste sobre la ausencia accidental de f.close().

-3

La forma más Pythonic para los siguientes códigos es:

try: 
    f = open("file", "r") 
    try: 
     line = f.readline() 
    finally: 
     f.close() 
except IOError: 
    <whatever> 

try: 
    f = open("file", "r") 
except IOError: 
    <whatever> 
else: 
    f.close() 
+0

He agregado el formato de código para usted; hace que sea más fácil de leer. Pero es posible que desee verificar dos veces para asegurarse de que no he roto la sangría. – andrewsi

+0

No, su versión no hace lo mismo que el código original. Incluso si agrega la llamada 'readline()' faltante, su versión no cierra el archivo si 'readline()' da como resultado un 'IOError'. –

Cuestiones relacionadas