Tengo un script Python (3) bastante grande que estoy tratando de optimizar.
Según tengo entendido, cuando usa with open(..., ...) as x, NO necesita usar .close() al final del bloque "con" (se cierra automáticamente).

También sé que DEBE agregar .close() (si no está utilizando with) después de que haya terminado de manipular el archivo, así:

f = open(..., ...)
f.write()
f.close()

En un intento de meter 3 líneas (arriba) en 1 línea, intenté cambiar esto:

with open(location, mode) as packageFile:
    packageFile.write()

En esto:

open(location, mode).write(content).close()

Lamentablemente, esto no funcionó y recibí este error:

Traceback (most recent call last):
  File "test.py", line 20, in <module>
    one.save("one.txt", sample)
  File "/home/nwp/Desktop/Python/test/src/one.py", line 303, in save
    open(location, mode).write(content).close()
AttributeError: 'int' object has no attribute 'close'

La misma línea funciona bien cuando elimino el .close() de esta manera:

open(location, mode).write(content)

¿Por qué open(location, mode).write(content).close() no funcionó y es seguro omitir la función .close()?

5
user5870134 13 may. 2016 a las 22:38

4 respuestas

La mejor respuesta

¿Es seguro omitir la función .close ()?

En las versiones actuales de CPython, el archivo se cerrará al final del ciclo for porque CPython usa el recuento de referencias como su mecanismo principal de recolección de basura, pero eso es un detalle de implementación, no una característica del lenguaje.

También citando directamente user2357112: if you ever run this code on a different Python implementation, or if CPython ever abandons reference counting, your write could be arbitrarily delayed or even lost completely.

¿Por qué no funcionó abrir (ubicación, modo) .write (contenido) .close ()?

Esto se debe a que estaba intentando llamar al método .close() al devolver open(location, mode).write(content).

1
Community 23 may. 2017 a las 10:28

También sé que DEBE agregar .close() después de que haya terminado de manipular el archivo

No si estás usando with.

¿Por qué no funcionó open(location, mode).write(content).close()

Porque en lugar de intentar cerrar el archivo, está intentando cerrar el valor de retorno de la llamada al método write, que es un número entero. No puedes cerrar un número entero.

¿es seguro omitir la función .close()?

No. Si alguna vez ejecuta este código en una implementación diferente de Python, o si CPython alguna vez abandona el conteo de referencias, su escritura podría retrasarse arbitrariamente o incluso perderse por completo.

Si realmente quiere meter esto en una sola línea, puede escribir una declaración de una sola línea with:

with open(location, mode) as packageFile: packageFile.write(whatever)

Esto se desaconseja, pero mucho menos se desanima que confiar en el finalizador del objeto de archivo para cerrar el archivo por usted.

1
user2357112 supports Monica 13 may. 2016 a las 19:49

Esto se debe a que el operador . (punto) funciona de izquierda a derecha. En a.b, b es un mensaje (llamada al método) pasado a a. Decir

a.b.c...

Lee

do b in a and return r1, then
do c in r1 and return r2, then
...

Ahora open devuelve un objeto que responde al mensaje read, pero read devuelve un str / bytes que no tiene método close.

Bdw, siempre usa un administrador de contexto, es decir, con with en dicho contexto. Y me pregunto qué tiene que ver esto con la optimización, ya que dijiste que lo estás haciendo mientras optimizas un script.

1
C Panda 13 may. 2016 a las 19:50

Me parece que el objetivo es que una función ocurra justo después de otra, sin embargo, eso no es lo que está sucediendo aquí.

Abrir (ubicación, modo) devuelve un archivo: https://docs.python.org/2/library/functions.html#open

En la sintaxis de

open(location, mode).write(content)

Esto es realmente equivalente a

file = open(location, mode)
file.write(content)

La declaración abierta se convierte en un archivo de tipo que tiene una función llamada write (). La razón por la que .close () no funciona es porque el archivo.write () no tiene una función llamada close (). Lo que está intentando hacer es file.function (). Function ().

En cualquier caso, tratar de optimizar su código reduciendo las líneas no acelerará notablemente el rendimiento, lo normal con la declaración debería ser igual de rápido. A menos que estés tratando de jugar golf en código, que es un tema completamente diferente.

¡Tenga un buen día!

1
OmniBro 13 may. 2016 a las 19:50