Si lee un archivo completo, ¿ content = open('Path/to/file', 'r').read()
está abierto el identificador de archivo hasta que salga el script? ¿Existe un método más conciso para leer un archivo completo?
Si lee un archivo completo, ¿ content = open('Path/to/file', 'r').read()
está abierto el identificador de archivo hasta que salga el script? ¿Existe un método más conciso para leer un archivo completo?
La respuesta a esa pregunta depende en cierta medida de la implementación particular de Python.
Para comprender de qué se trata todo esto, preste especial atención al file
objeto real . En su código, ese objeto se menciona solo una vez, en una expresión, y se vuelve inaccesible inmediatamente después de que read()
vuelve la llamada.
Esto significa que el objeto del archivo es basura. La única pregunta que queda es "¿Cuándo recogerá el recolector de basura el objeto de archivo?".
En CPython, que utiliza un contador de referencia, este tipo de basura se nota inmediatamente, por lo que se recogerá de inmediato. Esto no es generalmente cierto en otras implementaciones de Python.
Una mejor solución, para asegurarse de que el archivo esté cerrado, es este patrón:
with open('Path/to/file', 'r') as content_file:
content = content_file.read()
que siempre cerrará el archivo inmediatamente después de que finalice el bloque; incluso si ocurre una excepción.
Editar: para ponerle un punto más fino:
Aparte de file.__exit__()
, que se llama "automáticamente" en una with
configuración de administrador de contexto, la única otra forma que file.close()
se llama automáticamente (es decir, aparte de llamarlo explícitamente usted mismo) es a través de file.__del__()
. Esto nos lleva a la pregunta de cuándo __del__()
se llama?
Un programa escrito correctamente no puede suponer que los finalizadores se ejecutarán en algún momento antes de la finalización del programa.
- https://devblogs.microsoft.com/oldnewthing/20100809-00/?p=13203
En particular:
Los objetos nunca se destruyen explícitamente; sin embargo, cuando se vuelven inalcanzables, se pueden recolectar basura. Se permite a una implementación posponer la recolección de basura u omitirla por completo : es una cuestión de calidad de implementación cómo se implementa la recolección de basura, siempre que no se recolecten objetos que aún sean accesibles.
[...]
CPython actualmente utiliza un esquema de conteo de referencias con detección retrasada (opcional) de basura enlazada cíclicamente, que recolecta la mayoría de los objetos tan pronto como se vuelven inalcanzables, pero no se garantiza que recolecte basura que contenga referencias circulares.
- https://docs.python.org/3.5/reference/datamodel.html#objects-values-and-types
(El énfasis es mío)
pero como sugiere, otras implementaciones pueden tener otro comportamiento. Como ejemplo, PyPy tiene 6 implementaciones diferentes de recolección de basura .
__exit__()
en tales casos suena como un defecto de diseño.try
/finally
es complicado y la muy inútil utilidad de los controladores de limpieza quewith
resuelve. La diferencia entre "cerrar explícitamente" y "administrar conwith
" es que se llama al controlador de salida incluso si se produce una excepción. Podría poner elclose()
en unafinally
cláusula, pero eso no es muy diferente de usar en suwith
lugar, un poco más desordenado (3 líneas adicionales en lugar de 1), y un poco más difícil de conseguir.with foo() as f: [...]
es básicamente lo mismo quef = foo()
,f.__enter__()
[...] yf.__exit__()
con excepciones manejadas , por lo que__exit__
siempre se llama. Entonces el archivo siempre se cierra.Puedes usar pathlib .
Para Python 3.5 y superior:
Para versiones anteriores de Python, use pathlib2 :
Entonces:
Esta es la
read_text
implementación real :fuente
Bueno, si tiene que leer el archivo línea por línea para trabajar con cada línea, puede usar
O incluso mejor manera:
fuente
En lugar de recuperar el contenido del archivo como una sola cadena, puede ser útil almacenar el contenido como una lista de todas las líneas que comprende el archivo :
Como se puede ver, uno necesita agregar los métodos concatenados
.strip().split("\n")
a la respuesta principal en este hilo .Aquí,
.strip()
solo elimina los espacios en blanco y los caracteres de nueva línea en las terminaciones de toda la cadena del archivo, y.split("\n")
produce la lista real dividiendo la cadena completa del archivo en cada carácter de nueva línea \ n .Además, de esta manera, todo el contenido del archivo puede almacenarse en una variable, lo que puede desearse en algunos casos, en lugar de recorrer el archivo línea por línea como se indicó en esta respuesta anterior .
fuente