python中关于with以及contextlib的使用
一般在coding时,经常使用with来打开文件进行文件处理,然后无需执行close方法进行文件关闭.
with open('test.py','r' as f:
print(f.readline())
with的作用,类似于try...finally...
,提供一种上下文机制.如果需要使用with语句的类,就必须内部提供了两个内置函数__enter__和__exit__,前者在主体代码前执行,后者在主体代码后执行.看下下面的例子吧.
class Tt:
def output(self):
print('hello,world!')
def __enter__(self):
print('enter!!!')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('exit!!!')
if exc_type == ValueError:
return True
else:
return False
with Tt() as t:
t.output()
print('do something~~')
print('==================')
with Tt() as e:
raise ValueError('value error!')
print('==================')
with Tt() as e:
raise Exception('can not detect! ')
out:
enter!!!
hello,world!
do something~~
exit!!!
==================
enter!!!
exit!!!
==================
enter!!!
Traceback (most recent call last):
exit!!!
File "/Users/shane/PycharmProjects/Py_study/Base/S12/with_test.py", line 29, in <module>
raise Exception('can not detect! ')
Exception: can not detect!
是不是跟装饰器有点像?再来个contextlib吧!
contextlib是为了加强with语句,提供上下文机制的模块,它是通过Generator实现的。contextlib中的contextmanager作为装饰器来提供一种针对函数级别的上下文管理机制。下面看个例子吧:
import contextlib
free_list=[]
work_thread='alex'
@contextlib.contextmanager
def worker_state(state_list,work_thread):
state_list.append(work_thread)
try:
print('go on!!') #step1
yield #step2
finally:
print(state_list) #step5
state_list.remove(work_thread) #step6
print(state_list) #step7
with worker_state(free_list,work_thread):
print(123) #step3
print(456) #step4
out:
go on!!
123
456
['alex']
[]
contextlib.contextmanager 是python中内置的一个装饰器:执行with后面的函数时,先进入函数中执行,遇到yield时,跳出,执行下面的,最后执行函数中的finally
此种用法也可用来自动关闭socket
import contextlib,socket
@contextlib.contextmanager
def context_socket(host,port):
sk=socket.socket()
sk.bind((host,port))
sk.listen(5)
try:
yield sk #将sk返回,赋值给sock
finally:
sk.close()
with context_socket('127.0.0.1',8888) as sock:
print(sock)