Python With 的用法


**起因:在写聊天客户端的时候线程锁不知道怎么下手,try finally 觉得太沉重,想起来 With这个环境管理器。
里面涉及Python2的,但是和python3没太大区别,仅供需要参考
**


一、With语句是什么?

  • With:
    • 1.上下文管理器
    • 2.环境管理器
  • 我们平时写程序的时候需要收尾,很典型的一个就是Open,读取文件句柄,关闭文件句柄。
例:
  • file = open("/tmp/foo.txt");data = file.read();file.close()

  • 可能带来的问题:

    • 可能忘记关闭文件句柄
    • 文件读取数据异常
    • 下面看新版本
    try:
        f = open('xxx')
    except:
        print 'fail to open'
        exit(-1)
    try:
        do something
    except:
        do something
    finally:
         f.close()
    
    • 虽然捕获异常了,但是太长了,并不符合Python语言优雅的特性。
    • 下面我们的With出场:
    with open("/tmp/foo.txt") as file:
        data = file.read()
    

With工作原理

  • With后面的代码执行后,返回对象的__enter__()随即被调用,全部执行完毕后便调用__exit__()方法。
例:
class Sample:
    def __enter__(self):
        print "In __enter__()"
        return "Foo"
    def __exit__(self, type, value, trace):
        print "In __exit__()"
def get_sample():
    return Sample()
with get_sample() as sample:
    print "sample:", sample

输出:

bash-3.2$ ./with_example01.py
In __enter__()
sample: Foo
In __exit__()
  • 步骤:

    • 1、 enter()方法被执行
    • 2、enter()方法返回的值 - 这个例子中是”Foo”,赋值给变量’sample’
    • 3、执行代码块,打印变量”sample”的值为 “Foo” 4. exit()方法被调用
然后With还有一个好玩的运行异常管理
  • 回头看看__exit__()他又三个参数value, type 和 trace
例:
def __enter__(self): 
	return self 
def __exit__(self, type, value, trace): 
	print "type:", type 
	print "value:", value 
	print "trace:", trace 
def do_something(self): 
	bar = 1/0 
	return bar + 10 
	
with Sample() as sample: 
sample.do_something()

输出:

type: <type 'exceptions.ZeroDivisionError'>
value: integer division or modulo by zero
trace: <traceback object at 0x1004a8128>
Traceback (most recent call last):
  File "./with_example02.py", line 19, in <module>
    sample.do_something()
  File "./with_example02.py", line 15, in do_something
    bar = 1/0
ZeroDivisionError: integer division or modulo by zero
  • 实际上,With后面的代码抛出异常后,exit()方法被执行,其中关联的异常分别传给三个参数,就抛出异常了。
  • 跳过一个异常 我们可以这样做:
  • def __exit__(self, type, value, traceback): return isinstance(value, ZeroDivisionError)
  • 除了ZeroDivisionError其他正常抛出

相关术语

  • 要使用 with 语句,首先要明白上下文管理器这一概念。有了上下文管理器,with 语句才能工作。
  • 下面是一组与上下文管理器和with 语句有关的概念。
  • 上下文管理协议(Context Management Protocol):包含方法 enter() 和 exit(),支持该协议的对象要实现这两个方法。
  • 上下文管理器(Context Manager):支持上下文管理协议的对象,这种对象实现了__enter__() 和 exit() 方法。上下文管理器定义执行 with 语句时要建立的运行时上下文,负责执行 with 语句块上下文中的进入与退出操作。通常使用 with 语句调用上下文管理器,也可以通过直接调用其方法来使用。
  • 运行时上下文(runtime context):由上下文管理器创建,通过上下文管理器的 enter() 和__exit__() 方法实现,enter() 方法在语句体执行之前进入运行时上下文,exit() 在语句体执行完后从运行时上下文退出。with 语句支持运行时上下文这一概念。
  • 上下文表达式(Context Expression):with 语句中跟在关键字 with 之后的表达式,该表达式要返回一个上下文管理器对象。
  • 语句体(with-body):with 语句包裹起来的代码块,在执行语句体之前会调用上下文管理器的 enter() 方法,执行完语句体之后会执行__exit__() 方法。

梦想其实离你并不远,只是你在可以假装你没有,你不应该再拒绝自己的梦想。


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值