python上下文管理语句_python上下文管理,with语句

今天在网上看到一段代码,其中使用了with seam:初见不解其意,遂查询资料.

代码:

1 #! /usr/bin/env python

2 #-*- coding:utf-8 -*-

3 importtime4 from random importrandom5 from threading importThread,Semaphore6

7 sema = Semaphore(3)8

9 deffoo(tid):10 with sema:11 print("{} acquire sema".format(tid))12 wt = random() * 2

13 time.sleep(wt)14 print("{} release sema".format(tid))15

16 threads =[]17

18 for i in range(5):19 t = Thread(target=foo,args=(i,))20 threads.append(t)21 t.start()22

23 for t inthreads:24 t.join()

查询 python核心编程第二版,其中有个章节,专门介绍了with语句和上下文管理.

with语句,在Python2.6正式启用,和try-except-finally 类似,with语句也是用来简化代码的.Python中,并非任意符号都可以使用with语句,with语句仅仅工作于支持上下文管理协议的对象.

with应用场景:打开文件,日志,数据库,线程资源,简单同步,数据库连接等等.

1 with context_expr [as var]: ##context_expr:上下文表达式,[]可选2 with_suite

能和with一起使用的成员列表:

1 file2 decimal.Context3 thread.LockType4 threading.Lock5 threading.RLock6 threading.Condition7 threading.Semaphore8 threading.BoundedSemaphore

最最常见的with用法:

1 with open("file","r") as f:

for line in f:2 pass

上面的代码都做了什么操作?

程序试图打开一个文本,如果一切正常,把文本对象赋值给f,然后用迭代器遍历文本中的每一行.当完成时,关闭文本.

无论在这段代码的开始,中间,还是结束时发生了异常,都会执行清理的代码,此外文件仍然被会自动的关闭.

先上一个最简单的代码:

1 classContext:2 def __init__(self,name):3 self.name =name4 def __enter__(self):5 print("Begin.__enter__")6 returnself7 def __exit__(self, exc_type, exc_val, exc_tb):8 print("End.__exit__")9 defcontext(self):10 print("This is context ...{}".format(self.name))11

12 with Context("xurui") as context: ##如果带上 as 变量,那么__enter__()方法必须得返回一个东西,要不然会报错..13 context.context()14 with Context("xurui"):15 Context("xurui").context()

演示代码:

classSample:"""##执行__enter__方法,它将完成with语句块执行前的所有准备工作,如果with xx 后面带上参数,as val,那么__enter__返回值将赋值给

val,否则,丢弃返回值"""

def __enter__(self):print("In __enter__()")return "Foo" ##返回"Foo"给as Sample中的Sample

def __exit__(self, exc_type, exc_val, exc_tb):print("In __exit__()")defget_sample():print(type(Sample()))returnSample()

with get_sample() as Sample:print("sample:{}".format(Sample))

结果:

In__enter__()

sample:Foo

In__exit__()

但这都不是with的牛逼功能,with最强的地方,还是用来处理异常...

__exit__(),有三个参数,类型(异常类),值(异常实例),和回溯(回溯对象).

演示代码:

classSample:"""##执行__enter__方法,它将完成with语句块执行前的所有准备工作,如果with xx 后面带上参数,as val,那么__enter__返回值将赋值给

val,否则,丢弃返回值"""

def __enter__(self):returnselfdef __exit__(self, exc_type, exc_val, exc_tb):print("type:{},\nvalue:{},\ntrace:{}".format(exc_type,exc_val,exc_tb))defdo_something(self):

bar= 1 /0return bar + 10with Sample() as Sample:

Sample.do_something()print("sample:{}".format(Sample))

结果:

type:,

value:division by zero,

trace:Traceback (most recent call last):

File"C:/Users/xurui/PycharmProjects/q1/2017-03-01/error.py", line 55, in Sample.do_something()

File"C:/Users/xurui/PycharmProjects/q1/2017-03-01/error.py", line 51, indo_something

bar= 1 /0

ZeroDivisionError: division by zero

1 importqueue2 importcontextlib3

4

5 @contextlib.contextmanager6 defworker_state(xxx, val):7 xxx.append(val)8 #print(xxx)

9 try:10 yield

11 finally:12 xxx.remove(val)13 #print(xxx)

14

15

16 q =queue.Queue()17 li =[]18 q.put("xurui")19 with worker_state(li, 1):20 print("before", li)21 q.get()22 print("after", li)

自定义一个open文件

1 importcontextlib2

3

4 @contextlib.contextmanager5 defMyOpen(filename, mode):6 try:7 f = open(filename, mode, encoding='utf')8 exceptException as e:9 pass

10 else:11 yield f ##f return 给 as f的f

12 finally:13 f.close()14

15

16 with MyOpen("1.py", 'r') as f:17 ret =f.readlines()18 print(ret)

你可能感兴趣的:(python上下文管理语句)