2011-10-15 25 views
31
# Open new file to write 
file = None 
try: 
    file = open(filePath, 'w') 
except IOError: 
    msg = ("Unable to create file on disk.") 
    file.close() 
    return 
finally: 
    file.write("Hello World!") 
    file.close() 

El código anterior se extrajo de una función. Uno de sistema del usuario notifica un error en la línea:python try: excepto: finalmente

file.write("Hello World!") 

error:

AttributeError: 'NoneType' object has no attribute 'write' 

pregunta es, si pitón se pudo abrir archivo dado, 'excepto' ejecuta el bloque y tiene que return, pero el control se transfiere a la línea que está lanzando dado el error. El valor de la variable 'archivo' es 'Ninguno'.

¿Alguna sugerencia?

Respuesta

67

No debe escribir en el archivo en el bloque finally ya que las excepciones planteadas allí no serán detectadas por el bloque except.

El bock except se ejecuta si hay una excepción provocada por el bloque try. El finally bloque siempre ejecuta lo que suceda.

Además, no debería haber ninguna necesidad de inicializar la variable file en none.

El uso de return en el bloque except no omitirá el bloque finally. Por su propia naturaleza no se puede omitir, es por eso que quiere poner su código de "limpieza" allí (es decir, archivos de cierre).

lo tanto, si desea utilizar intento: excepto: por último, que debería estar haciendo algo como esto:

try: 
    f = open("file", "w") 
    try: 
     f.write('Hello World!') 
    finally: 
     f.close() 
except IOError: 
    print 'oops!' 

Una manera mucho más limpia de hacer esto es mediante el with declaración:

try: 
    with open("output", "w") as outfile: 
     outfile.write('Hello World') 
except IOError: 
    print 'oops!' 
+11

+1 para la declaración 'with' – gecco

+0

el código es muy clever.i aprender de ella – viprs

+1

Desafortunadamente,' with' no está presente en Python 2.4, por lo que no va a funcionar. – SummerBreeze

0

finalmente siempre se llama en el "final", incluso si ocurre una excepción. Puede usar esto para asegurarse de que los recursos abiertos estén cerrados (por ejemplo, una conexión de BD, un archivo, etc.).

Creo que malinterpretaste la semántica.

Su lógica debe estar en "intentar", debe tratar con excepciones en el bloque "excepto", y "finalmente" se ejecuta sin importar cómo termina su método, úsela para limpiar.

1

excepto que no se ejecuta (porque el tipo es IOError) es la parte final que arroja otro error de tipo AttributeError porque file = None.

27

Si el archivo no se abre, la línea file = open(filePath, 'w') falla, por lo que no se asigna nada a file.

Luego, se ejecuta la cláusula except, pero no hay nada en el archivo, por lo que file.close() falla.

La cláusula finally siempre se ejecuta, incluso si hubo una excepción. Y dado que file sigue siendo Ninguno, obtiene otra excepción.

Desea una cláusula else en lugar de finally para cosas que solo suceden si no hay una excepción.

try: 
     file = open(filePath, 'w') 
    except IOError: 
     msg = "Unable to create file on disk." 
     return 
    else: 
     file.write("Hello World!") 
     file.close() 

Por qué la else? El Python docs dicen:

The use of the else clause is better than adding additional code to the try clause because it avoids accidentally catching an exception that wasn’t raised by the code being protected by the try ... except statement.

En otras palabras, esto no va a coger un IOError de los write o close llamadas. Lo cual es bueno, porque entonces la razón no habría sido "No se puede crear el archivo en el disco". Habría sido un error diferente, uno para el que el código no estaba preparado. Es una buena idea no tratar de manejar esos errores.

+1

+1 para el 'else' infrautilizado – kindall

+0

Pero ¿qué sucede si file.write() genera una excepción, lo cual es completamente posible después de abrirlo, incluso a pesar de que se abrió con permisos de escritura. Es mejor incluir eso en el intento: bloque – jenming

+1

@jenming: bueno, casi cualquier cosa puede generar excepciones :) Sin embargo, en realidad debes tratar de manejar solo las excepciones que esperas. Si le preocupan las excepciones de 'file.write()', inclúyalo en 'try'; solo asegúrese de no incluir algo como 'file.write (" result:% s "% do_calculation())', ya que eso escondería excepciones de 'do_calculation'. –

3

lo que es la lógica en la inclusión de la

file.write("Hello World!")

dentro de la cláusula finally ?? Creo que debe incluirse en la cláusula try.

try: 
     file = open(filePath, 'w') 
     file.write("Hello World!") 
except IOError: 
     print("Unable to create file on disk.") 
finally: 
     file.close() 
0

Siempre es recomendable escribir la lógica o código que podría lanzar una excepción en el bloque try y utilizar el bloque finally para el cierre de los recursos.

+0

Irrelevante a la pregunta original. – stackoverflowuser2010

1

se puede hacer algo como esto:

try: 
    do_some_stuff() 
finally: 
    cleanup_stuff() 
1

Aquí es la solución más directa a su problema. Utilizo la expresión idiomática de buscar file_obj != None en el bloque finally.

Por cierto, debe tener en cuenta que file es un nombre de clase de Python, por lo que debe elegir un nombre de variable diferente.

file = None 
try: 
    file = open(filePath, 'w') 
except IOError: 
    msg = ("Unable to create file on disk.") 
    file.close() 
    return 
finally: 
    if file != None: 
     file.write("Hello World!") 
     file.close() 
Cuestiones relacionadas