2009-09-03 9 views
10

en leer el contenido de un archivo:Archivo abierto: ¿Es este el mal estilo de Python?

data = open(filename, "r").read() 

El archivo abierto inmediatamente deja de ser referenciado en cualquier lugar, por lo que el objeto de archivo con el tiempo se estrecha ... y no debería afectar a otros programas de usarlo, ya que el archivo es solo abierto para leer, no escribir.

EDIT: En realidad, esto me ha mordido en un proyecto que escribí - que me llevó a preguntar this cuestión. Los objetos de archivo se limpian solo cuando se queda sin memoria, no cuando se quedan sin controladores de archivo. Por lo tanto, si lo hace con demasiada frecuencia, podría terminar quedándose sin descriptores de archivos y causando que sus intentos de IO para abrir archivos generen excepciones.

+3

Tenga en cuenta que esto leerá todo el archivo en la memoria, sin importar cuán grande sea. Así que asegúrese de que sea un archivo que pueda manejar. Aparte de eso, estoy de acuerdo con las respuestas. – balpha

+0

@balpha: Pero las respuestas son contradictorias. ;) (Supongo que hizo el comentario antes de que todas las respuestas estuvieran en.) –

Respuesta

29

Sólo para que conste: Esto es sólo un poco más largo, y se cierra el archivo inmediatamente:

from __future__ import with_statement 

with open(filename, "r") as f: 
    data = f.read() 
+4

+1 Agregué 'import' en caso de que estén utilizando Python 2.5 :) –

+0

Pregunta de estilo de seguimiento: ¿es realmente horrible hacer * con open (" t1.py "," r ") como f: f. leer() * todo en una línea? Sé que no es tan fácil de leer, pero a menudo, la lectura del archivo es algo muy básico, y al siguiente que lee el código realmente no le importa cómo lo hiciste. –

+0

@Jenn D: Un punto del 'con' es limitar todo el procesamiento a un ámbito ordenado. Al poner 'with open() como f: f.read()' en una línea, se derrota el propósito del alcance de 'with'. –

3

No, es perfectamente razonable estilo Python OMI, según su razonamiento.

Actualización: Aquí hay muchos comentarios acerca de si los objetos de archivo se arreglan de inmediato o no. En lugar de especular, hice algunas excavaciones. Esto es lo que veo:


Desde un comentario en object.h de Python:

las macros Py_INCREF (op) y Py_DECREF (op) se utiliza para incrementar o recuentos de referencias decremento. Py_DECREF llama deallocator del objeto función cuando el refcount cae a 0

Buscando en fileobject.c de Python:

La tabla de funciones para el archivo de objetos puntos para funcionar file_dealloc. Esta función llama al close_the_file, que a su vez cierra el archivo.


por lo que parece razonable afirmar que en este momento, en CPython, cuando no hay más referencias a un objeto de archivo, que está cerrado y sin demora alguna. Si crees que esta interpretación es incorrecta, publica un comentario indicando por qué te sientes así.

+0

Razonable, sin embargo, pero los recursos del sistema operativo pueden no estar tan disponibles como usted desea. Por ejemplo, tratar de eliminar el archivo inmediatamente después de leerlo puede no funcionar porque los recursos del SO están en manos de las bibliotecas C subyacentes, incluso si el objeto 'archivo' de Python se ha recolectado como basura. Hasta que el sistema operativo piense que el archivo ya no está en uso, es posible que no pueda eliminarlo. –

+0

@ S. Lott: ¿está diciendo que un objeto 'archivo' recogido de basura no está cerrado (para que el sistema operativo sepa que ya no está en uso)? Esperaría * que al eliminar un objeto de archivo se cierre el archivo, pero no puedo encontrar nada en la documentación. – EOL

+5

Según tengo entendido, CPython (la implementación de referencia en la que la mayoría de la gente piensa cuando piensa en Python) destruye todos los objetos sin referencia a medida que abandonan el alcance. En ese caso, el objeto de archivo deja el alcance tan pronto como se completa la operación de lectura(). Entonces debería hacer exactamente lo que quieres. Sin embargo, eso no es un comportamiento garantizado. Otras implementaciones de Python (creo que Jython es un excelente ejemplo) pueden manejar la recolección de basura de manera diferente. Mi instinto es usar la implementación simple si sabes que estás usando CPython y no te importa la portabilidad. –

1

se ve bien para mí .. leí los archivos de esa frecuencia.

6

Es cierto que se va a cerrar con el tiempo, pero con el tiempo puede que no sea lo suficientemente pronto. Especialmente si está utilizando esto dentro de un bucle, el sistema podría quedarse sin manejadores de archivos antes de que el GC llegue a los objetos del archivo.

+0

¡oh, nunca pensé en eso! – Claudiu

+0

Pero si el archivo_obj es referencia contada ... va directamente a 0 y se borra inmediatamente? En CPython (?). – u0b34a0f6ae

+0

@ kaizer.se: aún no necesariamente se elimina inmediatamente. solo cuando CPython necesita más memoria. – Claudiu

4

El código funciona exactamente como usted dice que lo hace, pero es un mal estilo, sin embargo. Su código se basa en suposiciones que pueden ser ciertas ahora, pero no siempre serán ciertas. No es imposible que su código se ejecute en una situación en la que el archivo que se abre y no cierra importa. ¿Realmente vale la pena ese riesgo solo para guardar 1 o 2 líneas de código? No lo creo.

2

A pesar de que funciona como se esperaba, creo que falla en dos cargos:

  1. El código no se escala hasta la perfección, porque esté leyendo el archivo en la memoria, y esto puede o no puede ser necesariamente lo que quieres
  2. De acuerdo con el Zen de Python (prueba import this en el indicador de Python para recuperarlo) "explícita es mejor que implícita" y, al no cerrar el archivo explícitamente, podrías confundir a alguien que, en el futuro, quedará con tu código de mantenimiento

¡Realmente ayuda a ser explícito! Python fomenta el estilo explícito.

Aparte de eso, para un guión desechable, su estilo tiene sentido.

Quizás se beneficie de this answer.

Cuestiones relacionadas