¿Por qué es `with open ()` mejor para abrir archivos en Python?

Con frecuencia, cuando alguien publica su código, la gente agregará como un aparte que “usted debe usar with open('filename') as f syntax with open('filename') as f ahora “. Estoy de acuerdo en que la mayoría de las declaraciones f = open() antiguas no tienen un .close() acompañante, e incluso he respondido preguntas donde esta dependencia de “cierre implícito” fue la causa completa de su problema de progtwigción.

Sin embargo, en algunos casos, anidar su código dentro del bloque with parece crear otros inconvenientes al escribir el código. Por ejemplo, a veces me gusta usar una bandera al principio para decir writefile = True . Esto solo me permite abrir y cerrar el archivo si se va a utilizar, manteniendo el mismo hilo de procesamiento. En varios lugares del código puedo imprimir en pantalla o escribir en un archivo. (Me doy cuenta de que abriría la stdout estándar o el archivo al principio y utilizaría ese enfoque en su lugar).

Mi pregunta es: además de no tener que cerrar explícitamente el archivo, ¿existen otras razones para usar la syntax para manejar archivos , especialmente archivos de salida? (“Más python” por sí mismo no es una razón). Si este es un duplicado, me encantaría que me lo indicasen, pero no pude encontrarlo.

No hay otra ventaja with : garantizar que la limpieza sea lo único para lo que es.

De todos modos, necesita un bloque de ámbito para cerrar el archivo en caso de una excepción:

 writefile = random.choice([True, False]) f = open(filename) if writefile else None try: # some code or other finally: if writefile: f.close() 

Por lo tanto, lo que describe como una desventaja es realmente una desventaja del código correcto (en el caso de que se requiera limpieza), sin importar cómo lo escriba.

Queremos que se garantice que se realice alguna limpieza / finalización. Ese es el uso de with .

Sí, lo más común es que nos gustaría cerrar un archivo, pero podría dar otros ejemplos.

PEP 343 tiene un ejemplo sin archivo:

Una plantilla para asegurar que un locking, adquirido al inicio de un bloque, se libera cuando se deja el bloque:

 @contextmanager def locked(lock): lock.acquire() try: yield finally: lock.release() 

Utilizado de la siguiente manera:

 with locked(myLock): # Code here executes with myLock held. The lock is # guaranteed to be released when the block is left (even # if via return or by an uncaught exception). 

Además de no tener que cerrar explícitamente el archivo, ¿existen otras razones para usar la syntax para manejar archivos?

Creo que la razón principal para usar ContextManager durante la apertura del archivo es la idea de que este archivo se abrirá en cualquier caso, ya sea que todo esté bien o se produzca una excepción.

Es análogo para la siguiente afirmación.

 f = open(filename, 'w') try: pass finally: f.close() 

Por ejemplo, a veces me gusta usar una bandera al principio para decir writefile = True. Esto solo me permite abrir y cerrar el archivo si se va a utilizar, manteniendo el mismo hilo de procesamiento. En varios lugares del código puedo imprimir en pantalla o escribir en un archivo. (Me doy cuenta de que abriría la salida estándar o el archivo al principio y utilizaría ese enfoque en su lugar).

Esto describe el código con una gran cantidad de instrucciones if duplicadas.

además de no tener que cerrar explícitamente el archivo, ¿existen otras razones para usar la syntax para manejar archivos, especialmente archivos de salida?

Elimina la necesidad de escribir sus propios bloques finally , y estructura su código de modo que evite las declaraciones if duplicadas, y permite a los lectores localizar fácilmente el lugar donde se define un objeto de archivo (o una variable que contiene un objeto de archivo).

Así que en lugar de tu lío de banderas, puedes hacer:

 with (open('file') if condition else io.BufferedWriter(sys.stdout)) as f: pass