当前位置:   article > 正文

什么是 contextlib 模块?

contextlib

1、概述

Python 标准库的contextlib模块提供了为with语句分配资源的实用程序。

with Python 中的语句用于资源管理和异常处理。因此,它可以作为一个很好的Context Manager。当代码到达一个with语句时,它会临时分配资源。一旦with语句块完成,所有最初消耗的资源都会with被释放。

contextlib模块提供了三个函数:

  1. contextmanager(func)
  2. nested(mgr1[, mgr2[, …]])
  3. closing(thing)

2、contextmanager(func)

一个上下文管理器需要两个基本功能:enter()和__exit__()。您可以通过编写__enter__()和__exit__()函数在类中实现上下文管理器。通过在类中定义这些函数,我们可以将它与with语句一起使用以提供最佳资源分配。看看下面的代码:

class myFileHandler():
    def __init__(self, fname, method):
        print("I'm in contructor")
        self.file_obj = open(fname, method)
    def __enter__(self):
        print("I'm in ENTER block")
        return self.file_obj
    def __exit__(self, type, value, traceback):
        print("I'm in EXIT block")
        self.file_obj.close()

with myFileHandler("this_file.txt", "w") as example:
  ######### read write statements #########
  print("I'm in WITH block")
  pass
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

with 语句调用我们的类myFileHandler()。该__enter__()方法调用构造函数,使用传递的参数打开文件,并将文件对象返回给with语句,然后语句将其分配给example。 然后,with执行块中的语句。一旦它退出with块,exit()就会调用该方法,并优雅地终止进程。

可以使用该contextmanager(func)实用程序复制上述整个过程,但需要单独的__enter__()和__exit__()方法。看看下面的代码:

from contextlib import contextmanager

@contextmanager
def thisFunc(fname, method):
  print("This is the implicit ENTER block")
  my_file = open(fname, method)

  yield my_file
  
  print("This is the implicit EXIT block")
  my_file.close()


with thisFunc("this_file.txt", "w") as example:
  ######### read write statements #########
  print("I'm in WITH block")
  pass
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

公平地说,使用 contextmanager(func)(作为装饰器)使代码更具可读性和更容易理解。装修 contextmanager(func) 分为三个部分:

  1. yield 语句上面的部分做了__enter__()方法的作用。
  2. yield 语句返回一个迭代器到 with statementsas 子句中的目标- example。在这个阶段,控制权交给了with语句。
  3. yield 语句下面的部分执行 exit() 方法的作用。

3、nested(mgr1[, mgr2[, …]])

当我们需要使用语句调用多个函数时,contextlib模块为我们提供了一个实用程序with。nested()在这种情况下,该功能使我们的生活更轻松。考虑以下嵌套with语句:

with X as file_1:
    with Y as file_2:
        with Z as file_3:
            # statements for file_1, file_2, and file_3
  • 1
  • 2
  • 3
  • 4

嵌套函数将上面的代码压缩为一行

from contextlib import nested

with nested(X, Y, Z) as (file_1, file_2, file_3):
    # statements for file_1, file_2, and file_3
  • 1
  • 2
  • 3
  • 4

如果__exit__()一个的方法上下文管理器(X,Y,或Z)引发异常,则该异常不会被传递给所有外部上下文管理器。类似地,如果一个__exit__()一个的方法上下文管理器(X,Y,或Z)引发了异常,则该异常将被传递到的所有外上下文管理器。

4、closing(thing)

该 closing(thing) 方法返回一个在块完成时关闭的上下文管理器。例如:thing with

from contextlib import contextmanager
import socket

@contextmanager
def closing(thing):
    try:
        thing.connect("localhost", 8333)
        yield thing
    finally:
        thing.close()

sock = socket.socket()
with closing(sock) as my_sock:
    my_sock.listen()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

上面的代码将一个套接字对象发送到装饰的Context Manager closing(thing)。该上下文管理器建立连接并返回thing对象返回给with说法。当with语句块开始时,套接字对象关闭。

contextlib 模块的 closing(thing) 功能可以让你像这样编写上面的代码:

from contextlib import closing
import socket

with closing(socket.socket()) as my_sock:
    my_sock.listen()
  • 1
  • 2
  • 3
  • 4
  • 5
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/130310
推荐阅读
相关标签
  

闽ICP备14008679号