Python - with和上下文管理器

with关键字在Python里很常用,用作为上下文管理。例如打开文件,他可以避免我们获取文件句柄后,忘记关闭导致文件句柄还留在内存中存在风险,他是如何做到了,后续分析。

 

with open('./python1.py', 'r') as f:
    print(f.read())

例如给线程加锁。

 

lock = threading.RLock()
def job1():
    global A, lock
    lock.acquire()
    for i in range(10):
        A += 1
        print('job1', A)
    lock.release()
def job2():
    global A, lock
    with lock:
        # print(lock.__dict__)
        for i in range(10):
            A += 10
            print('job2', A)
with lock相当于在执行之前调用lock.acquire()加锁,在退出后调用lock.release()释放锁。  
如果我们没有release()那job2就永远无法获得这把锁了。死锁。

 

class MyOpen:
    def __init__(self, path, mode):
        self._path = path
        self._mode = mode

    def __enter__(self):
        self._handle = open(self._path, self._mode)
        return self._handle

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('游戏结束')
        self._handle.close()


with MyOpen('./python1.py', 'r') as f:
    print(f.read())
    
输出:
'''''''''''''''
    main()
游戏结束    

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

Myopen是一个上下文管理器。

with Myopen() as f 是上下文表达式。

with 会在进入时调用__enter__方法,在退出时调用__exit__方法。

这就是上下文管理协议的一个强大之处,异常可以在__exit__ 进行捕获并由你自己决定如何处理,是抛出呢还是在这里就解决了。在__exit__ 里返回 True(没有return 就默认为 return False),就相当于告诉 Python解释器,这个异常我们已经捕获了,不需要再往外抛了。

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

    yield file_handler

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


with open_func('./python1.py', 'r') as f:
    print(f.read())

 

如果只是希望将普通函数变成上下文管理器,我们并不需要去写一个很重的类,只需要用装饰器@contextlib.contextmanager就行,这里注意的是第7行用的是一个yield关键字,也就是函数返回的对象一个生成器,这里的目的看上去非常容易,就是让程序运行到yield关键字停住,意味着__enter__方法的结束,并且保存此时的状态,等待下一次进行__next__方法去触发__exit__方法。

15行,打break

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值