Administrador de contexto en Python

Gestión de recursos: en cualquier lenguaje de programación, el uso de recursos como operaciones de archivos o conexiones de bases de datos es muy común. Pero estos recursos son limitados en el suministro. Por lo tanto, el principal problema radica en asegurarse de liberar estos recursos después de su uso. Si no se liberan, se producirán pérdidas de recursos y el sistema puede ralentizarse o bloquearse. Sería muy útil si los usuarios tuvieran un mecanismo para la configuración y eliminación automática de recursos. En Python, se puede lograr mediante el uso de administradores de contexto que facilitan el manejo adecuado de los recursos. La forma más común de realizar operaciones con archivos es usando la palabra clave como se muestra a continuación: 

Python3

# Python program showing
# a use of with keyword
 
with open("test.txt") as f:  
    data = f.read()

Tomemos el ejemplo de la gestión de archivos. Cuando se abre un archivo, se consume un descriptor de archivo, que es un recurso limitado. Solo un cierto número de archivos puede ser abierto por un proceso a la vez. El siguiente programa lo demuestra. 

Python3

file_descriptors = []
for x in range(100000):
    file_descriptors.append(open('test.txt', 'w'))

Producción:

Traceback (most recent call last):
  File "context.py", line 3, in 
OSError: [Errno 24] Too many open files: 'test.txt'

Un mensaje de error que dice que hay demasiados archivos abiertos. El ejemplo anterior es un caso de fuga de descriptor de archivo. Sucede porque hay demasiados archivos abiertos y no están cerrados. Puede haber posibilidades de que un programador se olvide de cerrar un archivo abierto. 

Administrar recursos usando el administrador de contexto: suponga que un bloque de código genera una excepción o si tiene un algoritmo complejo con múltiples rutas de retorno, se vuelve engorroso cerrar un archivo en todos los lugares. Generalmente, en otros idiomas, cuando se trabaja con archivos , se usa try-except-finally para garantizar que el recurso del archivo se cierre después de su uso, incluso si hay una excepción. Python proporciona una manera fácil de administrar recursos: Administradores de contexto . Se utiliza la palabra clave with . Cuando se evalúa, debería dar como resultado un objeto que realiza la gestión de contexto. Los administradores de contexto se pueden escribir usando clases o funciones (con decoradores).

Creación de un administrador de contexto: al crear administradores de contexto usando clases, el usuario debe asegurarse de que la clase tenga los métodos: __enter__() y __exit__() . __enter__() devuelve el recurso que debe administrarse y __exit__() no devuelve nada, pero realiza las operaciones de limpieza. Primero, creemos una clase simple llamada ContextManager para comprender la estructura básica de la creación de administradores de contexto usando clases, como se muestra a continuación: 

Python3

# Python program creating a
# context manager
 
class ContextManager():
    def __init__(self):
        print('init method called')
         
    def __enter__(self):
        print('enter method called')
        return self
     
    def __exit__(self, exc_type, exc_value, exc_traceback):
        print('exit method called')
 
with ContextManager() as manager:
    print('with statement block')

Producción:

init method called
enter method called
with statement block
exit method called

En este caso, se crea un objeto ContextManager. Esto se asigna a la variable después de la palabra clave, es decir , gerente . Al ejecutar el programa anterior, se ejecuta lo siguiente en secuencia:

  • __en eso__()
  • __ingresar__()
  • cuerpo de la declaración (código dentro del bloque with )
  • __exit__()[los parámetros de este método se utilizan para gestionar excepciones]

Administración de archivos usando el administrador de contexto: apliquemos el concepto anterior para crear una clase que ayude en la administración de recursos de archivos. La clase FileManager ayuda a abrir un archivo, escribir/leer contenido y luego cerrarlo. 

Python3

# Python program showing
# file management using
# context manager
 
class FileManager():
    def __init__(self, filename, mode):
        self.filename = filename
        self.mode = mode
        self.file = None
         
    def __enter__(self):
        self.file = open(self.filename, self.mode)
        return self.file
     
    def __exit__(self, exc_type, exc_value, exc_traceback):
        self.file.close()
 
# loading a file
with FileManager('test.txt', 'w') as f:
    f.write('Test')
 
print(f.closed)

Producción:

True

  Gestión de archivos usando el administrador de contexto y la instrucción with: Al ejecutar el bloque with , las siguientes operaciones suceden en secuencia:

  • Se crea un objeto FileManager con test.txt como nombre de archivo y w (escribir) como modo cuando se ejecuta el método __init__.
  • El método __enter__ abre el archivo test.txt en modo de escritura (operación de configuración) y devuelve un objeto de archivo a la variable f .
  • El texto ‘Prueba’ se escribe en el archivo.
  • El método __exit__ se encarga de cerrar el archivo al salir del bloque with (operación de desmontaje). Cuando se ejecuta print(f.closed) , la salida es True ya que FileManager ya se ha ocupado de cerrar el archivo que, de lo contrario, debería hacerse explícitamente.

Gestión de conexión de base de datos usando el administrador de contexto: Vamos a crear un sistema de gestión de conexión de base de datos simple. La cantidad de conexiones de bases de datos que se pueden abrir a la vez también es limitada (al igual que los descriptores de archivos). Por lo tanto, los administradores de contexto son útiles para administrar las conexiones a la base de datos, ya que podría haber posibilidades de que el programador se olvide de cerrar la conexión. 

Python3

# Python program shows the
# connection management
# for MongoDB
 
from pymongo import MongoClient
 
class MongoDBConnectionManager():
    def __init__(self, hostname, port):
        self.hostname = hostname
        self.port = port
        self.connection = None
 
    def __enter__(self):
        self.connection = MongoClient(self.hostname, self.port)
        return self
 
    def __exit__(self, exc_type, exc_value, exc_traceback):
        self.connection.close()
 
# connecting with a localhost
with MongoDBConnectionManager('localhost', '27017') as mongo:
    collection = mongo.connection.SampleDb.test
    data = collection.find({'_id': 1})
    print(data.get('name'))

Gestión de la conexión de la base de datos utilizando el administrador de contexto y la instrucción with: Al ejecutar el bloque with , las siguientes operaciones suceden en secuencia:

  • Se crea un objeto MongoDBConnectionManager con localhost como nombre de host y 27017 como puerto cuando se ejecuta el método __init__.
  • El método __enter__ abre la conexión MongoDB y devuelve el objeto MongoDBConnectionManager a la variable mongo .
  • Se accede a la colección de prueba en la base de datos SampleDb y se recupera el documento con _id =1. Se imprime el campo de nombre del documento.
  • El método __exit__ se encarga de cerrar la conexión al salir del bloque with (operación de desmontaje).

Publicación traducida automáticamente

Artículo escrito por SamyuktaSHegde y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *