con declaración en Python

withLa declaración en Python se usa en el manejo de excepciones para hacer que el código sea más limpio y mucho más legible. Simplifica la gestión de recursos comunes como flujos de archivos. Observe el siguiente ejemplo de código sobre cómo el uso de la withdeclaración hace que el código sea más limpio.

# file handling
  
# 1) without using with statement
file = open('file_path', 'w')
file.write('hello world !')
file.close()
  
# 2) without using with statement
file = open('file_path', 'w')
try:
    file.write('hello world')
finally:
    file.close()
# using with statement
with open('file_path', 'w') as file:
    file.write('hello world !')

Tenga en cuenta que, a diferencia de las dos primeras implementaciones, no es necesario llamar file.close()cuando se usa la withinstrucción. La withdeclaración en sí misma garantiza la adquisición y liberación adecuadas de recursos. Una excepción durante la file.write()llamada en la primera implementación puede evitar que el archivo se cierre correctamente, lo que puede introducir varios errores en el código, es decir, muchos cambios en los archivos no entran en vigencia hasta que el archivo se cierra correctamente.

El segundo enfoque del ejemplo anterior se ocupa de todas las excepciones, pero el uso de la withdeclaración hace que el código sea compacto y mucho más legible. Por lo tanto, withla declaración ayuda a evitar errores y fugas al garantizar que un recurso se libere correctamente cuando el código que usa el recurso se ejecute por completo. La withdeclaración se usa popularmente con flujos de archivos, como se muestra arriba y con bloqueos, sockets, subprocesos y telnets, etc.

Compatibilidad con la declaración «with» en objetos definidos por el usuario

No hay nada especial open()que lo haga utilizable con la withdeclaración y se puede proporcionar la misma funcionalidad en los objetos definidos por el usuario. La declaración de respaldo withen sus objetos asegurará que nunca deje ningún recurso abierto.
Para usar withla declaración en objetos definidos por el usuario, solo necesita agregar los métodos __enter__()y __exit__()en los métodos del objeto. Considere el siguiente ejemplo para mayor aclaración.

# a simple file writer object
  
class MessageWriter(object):
    def __init__(self, file_name):
        self.file_name = file_name
      
    def __enter__(self):
        self.file = open(self.file_name, 'w')
        return self.file
  
    def __exit__(self):
        self.file.close()
  
# using with statement with MessageWriter
  
with MessageWriter('my_file.txt') as xfile:
    xfile.write('hello world')

Examinemos el código anterior. Si te fijas, lo que sigue a la withpalabra clave es el constructor de MessageWriter. Tan pronto como la ejecución ingresa al contexto de la withdeclaración, MessageWriterse crea un objeto y Python llama al __enter__()método. En este __enter__()método, inicialice el recurso que desea usar en el objeto. Este __enter__()método siempre debe devolver un descriptor del recurso adquirido.

¿Qué son los descriptores de recursos?
Estos son los identificadores proporcionados por el sistema operativo para acceder a los recursos solicitados. En el siguiente bloque de código, filehay un descriptor del recurso de flujo de archivos.

file = open('hello.txt')

En el MessageWriterejemplo anterior, el __enter__()método crea un descriptor de archivo y lo devuelve. El nombre xfileaquí se usa para referirse al descriptor de archivo devuelto por el __enter__()método. El bloque de código que utiliza el recurso adquirido se coloca dentro del bloque de la withinstrucción. Tan pronto como withse ejecuta el código dentro del bloque, __exit__()se llama al método. Todos los recursos adquiridos se liberan en el __exit__()método. Así es como usamos la withdeclaración con objetos definidos por el usuario.

Esta interfaz de __enter__()métodos __exit__()que proporciona el soporte de withdeclaraciones en objetos definidos por el usuario se denomina Administrador de contexto .

El módulo contextlib

Un administrador de contexto basado en clases, como se muestra arriba, no es la única forma de admitir la withdeclaración en objetos definidos por el usuario. El contextlibmódulo proporciona algunas abstracciones más basadas en la interfaz básica del administrador de contexto. Así es como podemos reescribir el administrador de contexto para el MessageWriterobjeto usando el contextlibmódulo.

from contextlib import contextmanager
  
class MessageWriter(object):
    def __init__(self, filename):
        self.file_name = filename
  
    @contextmanager
    def open_file(self):
        try:
            file = open(self.file_name, 'w')
            yield file
        finally:
            file.close()
  
# usage
message_writer = MessageWriter('hello.txt')
with message_writer.open_file() as my_file:
    my_file.write('hello world')

En este ejemplo de código, debido a la yielddeclaración en su definición, la función open_file()es una función generadora .
Cuando se llama a esta open_file()función, crea un descriptor de recursos llamado file. Este descriptor de recursos luego se pasa a la persona que llama y está representado aquí por la variable my_file. Después de ejecutar el código dentro del withbloque, el control del programa vuelve a la open_file()función. La open_file()función reanuda su ejecución y ejecuta el código que sigue a la yielddeclaración. Esta parte del código que aparece después de la yielddeclaración libera los recursos adquiridos. El @contextmanageraquí es un decorador .

La implementación anterior basada en clases y esta implementación basada en generadores de administradores de contexto es internamente la misma. Si bien el último parece más legible, requiere el conocimiento de generadores, decoradores y yield.

Publicación traducida automáticamente

Artículo escrito por Manthanchauhan 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 *