open
(
`file_path`
,
`¡hola mundo!`
)
archivo
# 2) no se usa con declaración
archivo
`hola mundo`
)
finalmente
:
archivo
.close()
,
`w`
`¡hola mundo!`
)
file.close ()
cuando se usa la instrucción with
. La declaración with
en sí misma garantiza que los recursos se adquieran y liberen correctamente. Una excepción durante file.write ()
en la primera implementación puede evitar que el archivo se cierre correctamente, lo que puede provocar varios errores en el código, es decir, muchos cambios en los archivos no surten efecto hasta que el archivo es correctamente cerrado.El segundo enfoque en el ejemplo anterior se ocupa de todas las excepciones, pero el uso de la declaración with
hace que el código sea compacto y mucho más legible. Por lo tanto, la declaración with
ayuda a evitar errores y fugas al garantizar que el recurso se libere correctamente cuando el código que usa el recurso se ejecute por completo. La declaración with
se usa comúnmente con secuencias de archivos como se muestra arriba, así como con bloqueos, sockets, subprocesos, telnets, etc.
Compatibilidad con la declaración "with" en objetos personalizados
No hay nada especial en open()
que lo hace utilizable con la declaración with
with
y la misma funcionalidad puede proporcionarse en objetos personalizados. La compatibilidad con las aserciones with
en sus objetos garantiza que nunca deje recursos abiertos.
Para usar el operador with
en objetos personalizados, solo necesita agregar el __enter __ ()
y __exit __ ()
métodos a los métodos del objeto. Considere el siguiente ejemplo para aclarar más.
# escritor de archivos simple
class
MessageWriter (
object
):
archivo
=
abrir
(
self
. file_name,
` w`
< clase de código = "simple">)
__ exit __ (
self
):
# usar con operador con MessageWriter
con MessageWriter (
`my_file.txt`
) como xfile:
Echemos un vistazo al código anterior. Si observa que la palabra clave with
sigue al constructor MessageWriter
. Una vez que la ejecución ingresa al contexto with
afirmando que se crea un objeto MessageWriter
y python llama al método __enter __ ()
. En este __enter __()
, inicialice el recurso que desea usar en el objeto. Este __enter __ ()
siempre debe devolver un identificador del recurso recibido.
¿Qué son los descriptores de recursos?
Son descriptores proporcionados por el sistema operativo para acceder a los recursos solicitados. En el siguiente bloque de código, file
es el descriptor de recursos del flujo de archivos.
file
< clase de código = "palabra clave"> = )
En el ejemplo proporcionado de MessageWriter
__enter __ ()
el método __enter __ ()
crea un descriptor de archivo y lo devuelve. El nombre xfile
se usa aquí para referirse al descriptor de archivo devuelto por el método __enter __ ()
. El bloque de código que usa el recurso resultante se coloca dentro del bloque de declaración with
. Una vez que se ejecuta el código dentro del bloque with
, el método __exit __ ()
es __exit __ ()
. Todos los recursos recibidos se liberan en __exit __()
. Así es como usamos la aserción with
con objetos definidos por el usuario.
Esta interfaz de método es __enter __ ()
y __exit __ ()
que brinda soporte para la declaración with
en objetos personalizados se llama Context Manager .
El módulo contextlib
El administrador de contexto basado en clases, como se muestra arriba, no es la única forma de admitir la instrucción with
en objetos personalizados. El módulo contextlib
proporciona algunas abstracciones más integradas en la interfaz base administrador de contexto Así es como podemos reescribir el administrador de contexto para el objeto MessageWriter
usando el módulo contextlib
.
class
MessageWriter (
objeto
=
nombre de archivo
self
):
< /código>
:
archivo
with message_writer.open_file() as my_file:
mi_archivo.escribir (
< / p>
En este ejemplo de código, debido a la declaración generador de funciones .
Cuando open_file ()
este open_file ()
, crea un identificador para un recurso llamado file
. Este descriptor de recursos luego se pasa a la persona que llama y se representa aquí mediante la variable my_file
. Después de ejecutar el código dentro del bloque with
, el control del programa vuelve a la función open_file ()
. La función open_file()
reanuda su ejecución y ejecuta el código siguiendo la declaración yield
. Esta parte del código que aparece después de la sentencia yield
libera los recursos resultantes. @contextmanager
aquí está