Explique en detalle con un administrador de contexto en Python

with Esta palabra clave es familiar para todos los que aprenden Python.

Al manipular objetos de texto, casi todo el mundo nos dejará utilizarlo, with openeste es un ejemplo de gestión de contexto. Debes estar bastante familiarizado con él, ya no diré tonterías.

with open('test.txt') as f:
    print f.readlines()

1. qué administrador de contexto?

Gramática básica

with EXPR as VAR:
    BLOCK

Primero aclara algunos conceptos

1. 上下文表达式:with open('test.txt') as f:
2. 上下文管理器:open('test.txt')
3. f 不是上下文管理器,应该是资源对象。

2. cómo administrador de contexto?

Para implementar esta gestión de contexto usted mismo, primero debe conocer el protocolo de gestión de contexto.

En pocas palabras, el método __enter__y __exit__se implementa en una clase, y una instancia de esta clase es un administrador de contexto.

Por ejemplo este ejemplo:

class Resource():
    def __enter__(self):
        print('===connect to resource===')
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        print('===close resource connection===')

    def operate(self):
        print('===in operation===')

with Resource() as res:
    res.operate()

Ejecutémoslo y repasemos la secuencia de impresión del registro. Puedes conocer el proceso de ejecución.

===connect to resource===
===in operation===
===close resource connection===

Es obvio a partir de este ejemplo que al escribir código, puede poner la conexión o adquisición del __enter__recurso y escribir el cierre del recurso __exit__.

3. por qué el administrador de contexto?

Pregúntese algunos por qué más cuando estudie y desarrolle el pensamiento sobre algunos detalles, que lo ayudarán a profundizar su comprensión de los puntos de conocimiento.

¿Por qué utilizar un administrador de contexto?

En mi opinión, esto está relacionado con el estilo elegante que defiende Python.

  1. Puede manipular (crear / adquirir / liberar) recursos de una manera más elegante, como operaciones de archivos y conexiones de bases de datos;
  2. Puede manejar las excepciones de una manera más elegante;

El primero, ya hemos tomado la conexión de recursos como ejemplo.

La mayoría de la gente ignorará el segundo tipo. Me enfocaré en eso aquí.

Como todos sabemos, el manejo de excepciones, generalmente se usa try...execept..para capturar procesos. Una desventaja de esto es que habrá una gran cantidad de agentes de manejo de excepciones en la lógica principal del código, lo que afectará en gran medida nuestra legibilidad.

Se puede utilizar algo mejor withpara manejar las excepciones ocultas.

Aún basado en el ejemplo de código anterior, vamos a 1/0este 一定会抛出异常的代码escrito operateen

class Resource():
    def __enter__(self):
        print('===connect to resource===')
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('===close resource connection===')
        return True

    def operate(self):
        1/0

with Resource() as res:
    res.operate()

Después de ejecutarlo, me sorprendió descubrir que no se informó de ningún error.

Este es un aspecto poderoso del protocolo de administración de contexto. Las excepciones pueden __exit__quedar atrapadas y usted puede decidir cómo lidiar con ellas, si lanzarlas o resolverlas aquí. A __exit__cambio True(no volver al valor predeterminado para devolver False), equivalente a decirle al intérprete de Python, hemos capturado la excepción, no es necesario que la descarte.

Al escribir una __exit__función, debes prestarle atención. Debe tener estos tres parámetros:

  • exc_type: tipo de excepción
  • exc_val: valor anormal
  • exc_tb: información de pila de errores anormal

Cuando el código lógico principal no informa una excepción, estos tres parámetros serán Ninguno.

4. ¿Cómo contextlib?

En el ejemplo anterior, acabamos de escribir una clase para construir un administrador de contexto. Si solo desea implementar una función simple, escribir una clase es un poco complicado. En este momento, pensamos, si solo se puede escribir una función para implementar el administrador de contexto.

Python ha pensado mucho en este punto. Nos proporciona un decorador.Puedes convertir este objeto de función en un administrador de contexto siempre que implementes el contenido de la función de acuerdo con su protocolo de código.

Seguimos el protocolo contextlib para implementar un administrador de contexto para abrir archivos (con open).

import contextlib

@contextlib.contextmanager
def open_func(file_name):
    # __enter__方法
    print('open file:', file_name, 'in __enter__')
    file_handler = open(file_name, 'r')

    # 【重点】:yield
    yield file_handler

    # __exit__方法
    print('close file:', file_name, 'in __exit__')
    file_handler.close()
    return

with open_func('/Users/MING/mytest.txt') as file_in:
    for line in file_in:
        print(line)

En la función decorada, debe ser un generador (con rendimiento), y el código antes de rendimiento es equivalente __enter__al contenido dentro. El código después de rendimiento es equivalente __exit__al contenido en.

El código anterior solo puede lograr el primer propósito del administrador de contexto (administrar recursos), pero no el segundo propósito (manejar excepciones).

Si desea manejar excepciones, puede cambiarlo a lo siguiente.

import contextlib

@contextlib.contextmanager
def open_func(file_name):
    # __enter__方法
    print('open file:', file_name, 'in __enter__')
    file_handler = open(file_name, 'r')

    try:
        yield file_handler
    except Exception as exc:
        # deal with exception
        print('the exception was thrown')
    finally:
        print('close file:', file_name, 'in __exit__')
        file_handler.close()

        return

with open_func('/Users/MING/mytest.txt') as file_in:
    for line in file_in:
        1/0
        print(line)

Parece que mientras se mencione el administrador de contexto, la mayoría de la gente hablará sobre el ejemplo clásico de abrir archivos.

Pero en el desarrollo real, hay muchos ejemplos de administradores de contexto que se pueden utilizar. Permítanme darles un ejemplo.

En OpenStack, cuando crea una instantánea de una máquina virtual, debe crear una carpeta temporal para almacenar la imagen de la instantánea local. Después de crear la imagen de la instantánea local, cargue la imagen en Glance. Luego elimine este directorio temporal.

La lógica principal de este código es 创建快照, y 创建临时目录pertenece a la condición previa 删除临时目录, es el toque final.

Aunque la cantidad de código es pequeña y la lógica no es complicada, la 创建临时目录,使用完后再删除临时目录función " " es necesaria en muchos lugares de un proyecto. Si este procesamiento lógico se puede escribir como una función de herramienta como administrador de contexto, la reutilización del código La tasa también se mejora considerablemente.

El código es así

En resumen, existen tres beneficios de utilizar un administrador de contexto:

  1. Mejorar la tasa de reutilización de código;
  2. Mejora la elegancia del código;
  3. Mejorar la legibilidad del código;

Recomiendo mi libro electrónico original " PyCharm Chinese Guide ", que contiene una gran cantidad (300) de ilustraciones , está bien hecho y es digno de una colección de todos los ingenieros de Python.

La dirección es: http://pycharm.iswbm.com

Supongo que te gusta

Origin blog.csdn.net/weixin_36338224/article/details/108994968
Recomendado
Clasificación