with
Hoy me encontré con la declaración de Python por primera vez. ¡He estado usando Python a la ligera durante varios meses y ni siquiera sabía de su existencia! Dado su estado algo oscuro, pensé que valdría la pena preguntar:
- ¿Para qué está
with
diseñada la declaración de Python ? - Para que lo usas?
- ¿Hay algún problema que deba tener en cuenta o antipatrones comunes asociados con su uso? ¿Algún caso en el que sea mejor usar
try..finally
quewith
? - ¿Por qué no se usa más ampliamente?
- ¿Qué clases de biblioteca estándar son compatibles con él?
with
en la documentación de Python 3.Respuestas:
Creo que esto ya ha sido respondido por otros usuarios antes que yo, por lo que solo lo agrego en aras de la exhaustividad: la
with
declaración simplifica el manejo de excepciones al encapsular tareas comunes de preparación y limpieza en los llamados administradores de contexto . Se pueden encontrar más detalles en PEP 343 . Por ejemplo, laopen
declaración es un administrador de contexto en sí mismo, que le permite abrir un archivo, mantenerlo abierto siempre que la ejecución esté en el contexto de lawith
declaración donde lo usó y cerrarlo tan pronto como abandone el contexto, sin importar si lo ha dejado debido a una excepción o durante el flujo de control regular. Por lo tanto, lawith
declaración puede usarse de manera similar al patrón RAII en C ++: el recurso adquiere algunoswith
declaración y publicado cuando abandonas elwith
contexto.Algunos ejemplos son: abrir archivos usando
with open(filename) as fp:
, adquirir bloqueos usandowith lock:
(dondelock
es una instancia dethreading.Lock
). También puede construir sus propios gestores de contexto utilizando elcontextmanager
decorador decontextlib
. Por ejemplo, a menudo uso esto cuando tengo que cambiar el directorio actual temporalmente y luego regresar a donde estaba:Aquí hay otro ejemplo que redirige temporalmente
sys.stdin
,sys.stdout
ysys.stderr
a algún otro identificador de archivo y los restaura más tarde:Y finalmente, otro ejemplo que crea una carpeta temporal y la limpia al salir del contexto:
fuente
with
declaración está diseñada para llenar una variable con datos hasta que se completen las instrucciones y luego liberar la variable?with open('myScript.py', 'r') as f: pass
. Que esperaba para ser capaz de llamar a la variablef
para ver el contenido del texto del documento, ya que esto es lo que aparecería si el documento se asigna af
través de un habitualopen
declaración:f = open('myScript.py').read()
. Pero en cambio me dieron la siguiente:<_io.TextIOWrapper name='myScript.py' mode='r' encoding='cp1252'>
. Qué significa eso?with
no elimina la necesidadread
del archivo real. Laswith
llamadasopen
, no sabe lo que necesita hacer con él, es posible que desee hacer una búsqueda, por ejemplo.with
declaración puede llenar una variable con datos o hacer algún otro cambio en el entorno hasta que se completen las instrucciones que contiene, y luego se realiza cualquier tipo de limpieza que sea necesaria. Los tipos de limpieza que se pueden hacer son cosas como cerrar un archivo abierto, o como lo ha hecho @Tamas en este ejemplo, cambiar los directorios a donde estaba antes, etc. Dado que Python tiene recolección de basura, liberar una variable no es importante caso de usowith
generalmente se usa para otros tipos de limpieza.Sugeriría dos conferencias interesantes:
1. La
with
declaración se usa para ajustar la ejecución de un bloque con métodos definidos por un administrador de contexto. Esto permitetry...except...finally
encapsular patrones de uso comunes para una reutilización conveniente.2. Podrías hacer algo como:
O
O (Python 3.1)
O
3. No veo ningún antipatrón aquí.
Citando Sumérgete en Python :
4. Supongo que está relacionado con el hábito de los programadores de usar
try..catch..finally
declaraciones de otros lenguajes.fuente
with
.La
with
declaración de Python es soporte de lenguaje incorporado delResource Acquisition Is Initialization
idioma comúnmente usado en C ++. Su objetivo es permitir la adquisición y liberación segura de los recursos del sistema operativo.La
with
declaración crea recursos dentro de un ámbito / bloque. Escribe su código utilizando los recursos dentro del bloque. Cuando el bloque sale, los recursos se liberan sin importar el resultado del código en el bloque (es decir, si el bloque sale normalmente o debido a una excepción).Muchos recursos en la biblioteca de Python que obedecen el protocolo requerido por la
with
declaración y, por lo tanto, se pueden usar de forma inmediata. Sin embargo, cualquiera puede crear recursos que se puedan utilizar en una declaración con implementando el protocolo bien documentado: PEP 0343Úselo cada vez que adquiera recursos en su aplicación que deben abandonarse explícitamente, como archivos, conexiones de red, bloqueos y similares.
fuente
Nuevamente para completar, agregaré mi caso de uso más útil para las
with
declaraciones.Hago mucha informática científica y para algunas actividades necesito la
Decimal
biblioteca para cálculos de precisión arbitrarios. En alguna parte de mi código necesito alta precisión y para la mayoría de las otras partes necesito menos precisión.Establezco mi precisión predeterminada en un número bajo y luego lo uso
with
para obtener una respuesta más precisa para algunas secciones:Lo uso mucho con la prueba hipergeométrica que requiere la división de grandes números como factoriales de forma. Cuando hace cálculos a escala genómica, debe tener cuidado con los errores de redondeo y desbordamiento.
fuente
Un ejemplo de un antipatrón podría ser usar el
with
interior de un bucle cuando sería más eficiente tenerwith
el bucle externopor ejemplo
vs
La primera forma es abrir y cerrar el archivo para cada uno, lo
row
que puede causar problemas de rendimiento en comparación con la segunda forma con abrir y cerrar el archivo una sola vez.fuente
Ver PEP 343 - La declaración 'con' , hay una sección de ejemplo al final.
fuente
los puntos 1, 2 y 3 están razonablemente bien cubiertos:
4: es relativamente nuevo, solo está disponible en python2.6 + (o python2.5 usando
from __future__ import with_statement
)fuente
La declaración with funciona con los llamados gestores de contexto:
http://docs.python.org/release/2.5.2/lib/typecontextmanager.html
La idea es simplificar el manejo de excepciones haciendo la limpieza necesaria después de abandonar el bloque 'con'. Algunos de los elementos integrados de Python ya funcionan como gestores de contexto.
fuente
Otro ejemplo de soporte inmediato, y uno que puede ser un poco desconcertante al principio cuando está acostumbrado a la forma en que se
open()
comporta incorporado , sonconnection
objetos de módulos de bases de datos populares como:Los
connection
objetos son administradores de contexto y, como tales, se pueden usar listos para usar en unwith-statement
, sin embargo, cuando se usa la nota anterior que:Esto significa que el programador debe tener cuidado de cerrar la conexión, pero permite adquirir una conexión y usarla en múltiples
with-statements
, como se muestra en los documentos de psycopg2 :En el ejemplo anterior, notará que los
cursor
objetos depsycopg2
también son administradores de contexto. De la documentación relevante sobre el comportamiento:fuente
En python, generalmente, la declaración " con " se usa para abrir un archivo, procesar los datos presentes en el archivo y también para cerrar el archivo sin llamar a un método close (). La declaración "con" simplifica el manejo de excepciones al proporcionar actividades de limpieza.
Forma general de con:
nota: no es necesario cerrar el archivo llamando a close () sobre file-var.close ()
fuente