¿Cuál es el python «con la» declaración diseñado para?

Me encontré con el Python with declaración por primera vez el día de hoy. He estado usando Python ligeramente por varios meses y ni siquiera sabía de su existencia! Dada su algo oscura estado, pensé que valdría la pena preguntar:

  1. ¿Cuál es el Python with declaración
    diseñado para ser utilizado para?
  2. ¿
    utilizas?
  3. Hay
    trampas tengo que ser consciente de, o
    común anti-patrones asociados con
    su uso? Cualquier de los casos donde es mejor usar try..finally de with?
  4. ¿Por qué no se utiliza más ampliamente?
  5. Que la biblioteca estándar de clases son compatibles con ella?
  • Sólo para el registro, aquí es with en Python 3 documentación.
  • viniendo de una Java de fondo, me ayuda a recordar como el correspondiente «pruebe con» recursos en Java, incluso si eso puede no ser del todo correcta.
InformationsquelleAutor fmark | 2010-06-10

10 Kommentare

  1. 366
    1. Creo que esto ya ha sido respondido por otros usuarios antes de mí, así que sólo agregar que en aras de la exhaustividad: la with declaración simplifica el manejo de excepciones mediante la encapsulación de preparación común y tareas de limpieza en los llamados contexto de los gerentes. Más detalles se pueden encontrar en PEP 343. Por ejemplo, el open declaración es un contexto manager en sí misma, que permite abrir un archivo, mantenerlo abierto mientras el tiempo de ejecución es en el contexto de la with declaración en la que se utiliza, y cerca de él tan pronto como usted deje el contexto, no importa si usted tiene a la izquierda porque de una excepción o durante el flujo de control. El with declaración por lo tanto puede ser utilizado de manera similar a los RAII patrón en C++: algunos de los recursos es adquirido por el with declaración y se libera cuando salga de la with contexto.

    2. Algunos ejemplos son: la apertura de los archivos utilizando with open(filename) as fp:, la adquisición de bloqueos utilizando with lock: (donde lock es una instancia de threading.Lock). Usted también puede construir su propio contexto managers, con la contextmanager decorador de contextlib. Por ejemplo, a menudo utilizo esta cuando tengo que cambiar el directorio actual de forma temporal y, a continuación, regresar a donde estaba:

      from contextlib import contextmanager
      import os
      
      @contextmanager
      def working_directory(path):
          current_dir = os.getcwd()
          os.chdir(path)
          try:
              yield
          finally:
              os.chdir(current_dir)
      
      with working_directory("data/stuff"):
          # do something within data/stuff
      # here I am back again in the original working directory

      He aquí otro ejemplo que temporalmente redirige sys.stdin, sys.stdout y sys.stderr a algún otro identificador de archivo y restaura más adelante:

      from contextlib import contextmanager
      import sys
      
      @contextmanager
      def redirected(**kwds):
          stream_names = ["stdin", "stdout", "stderr"]
          old_streams = {}
          try:
              for sname in stream_names:
                  stream = kwds.get(sname, None)
                  if stream is not None and stream != getattr(sys, sname):
                      old_streams[sname] = getattr(sys, sname)
                      setattr(sys, sname, stream)
              yield
          finally:
              for sname, stream in old_streams.iteritems():
                  setattr(sys, sname, stream)
      
      with redirected(stdout=open("/tmp/log.txt", "w")):
           # these print statements will go to /tmp/log.txt
           print "Test entry 1"
           print "Test entry 2"
      # back to the normal stdout
      print "Back to normal stdout again"

      Y, por último, otro ejemplo de que crea una carpeta temporal y lo limpia al salir del contexto:

      from tempfile import mkdtemp
      from shutil import rmtree
      
      @contextmanager
      def temporary_dir(*args, **kwds):
          name = mkdtemp(*args, **kwds)
          try:
              yield name
          finally:
              shutil.rmtree(name)
      
      with temporary_dir() as dirname:
          # do whatever you want
    • Gracias por la adición de la comparación a RAII. Como un programador de C++ que me dijo todo lo que necesitaba saber.
    • Bueno por lo que me deja esto en claro. Estás diciendo que el with instrucción está diseñada para satisfacer una variable con datos hasta las instrucciones de la sección que se completa y, a continuación, libre de la variable?
    • Porque yo lo he utilizado para abrir un py secuencia de comandos. with open('myScript.py', 'r') as f: pass. Esperaba ser capaz de llamar a la variable f para ver el contenido de texto del documento, ya que esto es lo que aparecería si el documento fueron asignados a f a través de un regular open declaración: f = open('myScript.py').read(). Pero en vez de eso me dieron la siguiente: <_io.TextIOWrapper name='myScript.py' mode='r' encoding='cp1252'>. ¿Qué significa esto?
    • el uso de with no elimina la necesidad de read el archivo real. El with llamadas open – no sabes lo que tienes que hacer con esto – es posible que desee hacer una búsqueda, por ejemplo.
  2. 85

    Yo sugeriría dos interesantes conferencias:

    • PEP 343 El «con» Declaración de
    • Effbot Comprensión de Python
      «con la» declaración de

    1.
    El with declaración se utiliza para envolver la ejecución de un bloque con los métodos definidos por un contexto manager. Esto permite común try...except...finally los patrones de uso para ser encapsulado por conveniente reutilizar.

    2.
    Se podría hacer algo como:

    with open("foo.txt") as foo_file:
        data = foo_file.read()

    O

    from contextlib import nested
    with nested(A(), B(), C()) as (X, Y, Z):
       do_something()

    O (Python 3.1)

    with open('data') as input_file, open('result', 'w') as output_file:
       for line in input_file:
         output_file.write(parse(line))

    O

    lock = threading.Lock()
    with lock:
        # Critical section of code

    3.
    Yo no veo ninguna Antipattern aquí.

    Citando Inmersión en Python:

    try..finalmente es bueno. con es mejor.

    4.
    Supongo que está relacionado con los programadores del hábito de uso try..catch..finally declaración de otros idiomas.

    • Es realmente entra en su cuenta cuando usted está tratando de enhebrar la sincronización de los objetos. Relativamente rara en Python, pero cuando usted los necesita, usted realmente necesita with.
    • diveintopython.org es hacia abajo (de forma permanente?). Reflejado en diveintopython.net
    • Ejemplo de una buena respuesta, abra el archivo es un buen ejemplo que muestra el detrás de las escenas de apertura,io,el cierre de las operaciones de archivos están ocultos limpiamente con un nombre de referencia personalizado
    • diveintopython3.org es un enlace roto.
  3. 36

    El Python with declaración es incorporado en el soporte de idiomas de la la Adquisición de Recurso Es la Inicialización lenguaje comúnmente utilizado en C++. Está pensado para permitir la adquisición y liberación de recursos del sistema operativo.

    La with instrucción crea los recursos dentro de un ámbito de aplicación/bloque. Se escribe el código de uso de los recursos dentro del bloque. Cuando se cierra el bloque de los recursos que se limpiamente en libertad sin importar el resultado del código en el bloque (es decir, si el bloque termina normalmente o debido a una excepción).

    Muchos de los recursos de la biblioteca de Python que cumplan con el protocolo requerido por la with declaración y lo puede usar con ella fuera de la caja. Sin embargo, cualquier persona puede hacer que los recursos que se pueden utilizar en un comunicado por la aplicación de la bien documentada protocolo: PEP 0343

    Utilizarlo siempre que adquirir recursos en su aplicación que debe ser explícitamente cedida, tales como archivos, conexiones de red, bloqueos y similares.

  4. 25

    Un ejemplo de un antipattern podría ser la utilización de la with dentro de un bucle cuando sería más eficiente que la with fuera del bucle

    por ejemplo

    for row in lines:
        with open("outfile","a") as f:
            f.write(row)

    vs

    with open("outfile","a") as f:
        for row in lines:
            f.write(row)

    La primera forma es la de abrir y cerrar el archivo para cada row que puede causar problemas de rendimiento en comparación con el segundo modo con que abre y cierra el archivo de una sola vez.

  5. 25

    De nuevo para la integridad voy a añadir mi más útil en los casos de uso para with declaraciones.

    Hago un montón de computación científica y para algunas de las actividades que necesito el Decimal biblioteca arbitrarias de los cálculos de precisión. Alguna parte de mi código necesito de alta precisión y para la mayoría de las otras piezas que necesitan menos precisión.

    Me puse mi defecto de precisión para un bajo número y, a continuación, utilizar with para obtener una respuesta más precisa para algunas de las secciones:

    from decimal import localcontext
    
    with localcontext() as ctx:
        ctx.prec = 42   # Perform a high precision calculation
        s = calculate_something()
    s = +s  # Round the final result back to the default precision

    Lo uso mucho con el Hipergeométrica de Prueba que requiere la división de los grandes números resultantes de la factoriales. Al hacer escala genómica cálculos que usted tiene que tener cuidado de redondeo y errores de desbordamiento.

  6. 4

    los puntos 1, 2, y 3 razonablemente bien cubiertos:

    4: es relativamente nuevo, sólo disponible en python2.6+ (o python2.5 uso de from __future__ import with_statement)

  7. 2

    Otro ejemplo para fuera-de-la-caja de soporte, y una que podría ser un poco desconcertante al principio, cuando estás acostumbrado a la forma integrada en open() se comporta, se connection objetos de la popular base de datos de módulos tales como:

    La connection objetos contexto de los gerentes y, como tal, puede ser utilizado fuera de la caja en un with-statement, sin embargo, al utilizar la nota anterior que:

    Cuando el with-block está terminado, ya sea con una excepción o sin, la conexión no está cerrada. En caso de que el with-block termina con una excepción, se deshace la transacción, de lo contrario la transacción es confirmada.

    Esto significa que el programador tiene que tener cuidado de cerrar la conexión en sí, sino que permite adquirir una conexión, y utilizar en múltiples with-statements, como se muestra en la psycopg2 docs:

    conn = psycopg2.connect(DSN)
    
    with conn:
        with conn.cursor() as curs:
            curs.execute(SQL1)
    
    with conn:
        with conn.cursor() as curs:
            curs.execute(SQL2)
    
    conn.close()

    En el ejemplo anterior, se observará que el cursor objetos de psycopg2 también en el contexto de los gerentes. A partir de la documentación pertinente en el comportamiento:

    Cuando un cursor sale de la with-block está cerrada, la liberación de cualquier tipo de recurso que eventualmente asociados con él. El estado de la transacción no se ve afectada.

  8. 2

    En python, en general, «con» declaración se utiliza para abrir un archivo, el proceso de los datos presentes en el archivo, y también para cerrar el archivo sin necesidad de llamar a un método close (). «con la» instrucción hace que el manejo de excepciones de forma más sencilla, proporcionando actividades de limpieza.

    Forma General de con:

    with open(“file name”, mode”) as file-var:
        processing statements

    nota: no hay necesidad de cerrar el archivo al llamar a close() archivo-var.close()

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea