python学习笔记:利用contextlib和@contextmanager实现with语句上下文实例

import hashlib
from contextlib import contextmanager
#contextlib
'''
任何对象,只要正确实现了上下文管理,就可以用于with语句。
实现上下文管理是通过__enter__和__exit__这两个方法实现的,
也可以通过@contextmanager和closing函数实现
'''
print('用contextlib实现在函数调用前后打印log的功能:')
print('(1)contextlib: with...as...语句')
class Call(object):
	def __init__(self, func):
		self.__func = func
	
	def __enter__(self):
		print('Call %s()' % self.__func.__name__)
		return self
	
	def __exit__(self, exc_type, exc_value, traceback):
		if exc_type:
			print('Error')
		else:
			print('%s() End' % self.__func.__name__)
	
	def doProcess(self):
		self.__func()

def testFunc():
	print('I am testFunc, I am doing something...')

'''
执行顺序:
1,执行Call里面的__enter__函数
2,然后执行with语句里面的c.doProcess()
3,再执行Call里面的__exit__函数
结果:
	Call testFunc()
	I am testFunc, I am doing something...
	testFunc() End
'''
with Call(testFunc) as c:
	c.doProcess()

#用@contextmanager实现和上面一样的功能,在函数调用前后打印log
print('(2)contextlib: with...as...语句,用@contextmanager实现')
from contextlib import contextmanager
class Call2(object): #不用实现__enter__和__exit__函数了
	def __init__(self, func):
		self.__func = func
	
	def doProcess(self):
		self.__func()

@contextmanager
def callWraper(func):
	print('Call %s()' % func.__name__)
	c = Call2(func)
	yield c
	print('%s() End' % func.__name__)

'''
执行流程:
1, with语句先执行callWraper函数里面yield之前的语句
2,yield调用会执行with语句内部的所有语句c.doProcess()
3,最后执行yield之后的语句
'''
with callWraper(testFunc) as c:
	c.doProcess()

#实现用with语句可以在用户执行操作前连接数据库,在执行完操作后关闭数据库的功能

#由字符串获取md5摘要信息串
def md5DigestGet(str):
	str += '!@#$%^'  #为了使简单的字符串不被黑客破解,将字符串添油加醋
	md5 = hashlib.md5()
	md5.update(str.encode('utf-8'))
	return md5.hexdigest()

class myDb(object):
	def __init__(self, users):
		self.__linkFlag = False #连接标志
		self.__usersLoginDigests = {} #保存用户名和密码的摘要信息
		for name, passward in users.items():
			md5Digest = md5DigestGet(name + passward)
			self.__usersLoginDigests[name] = md5Digest
	
	def getDbInfo(self):
		return self.__usersLoginDigests
	
	def loginCheck(self, name, passward):
		if md5DigestGet(name + passward) == self.getDbInfo()[name]:
			print('%s Login success' % name)
		else:
			print('%s Login fail' % name)

	def linkDb(self):
		self.__linkFlag = True
		return self.loginCheck
	
	def unlinkDb(self):
		self.__linkFlag = False

def linkDb(db): #连接到数据库
	print('Trying to link to db...')
	checkFunc = db.linkDb()
	print('Link db success..')
	return checkFunc

def unlinkDb(db):
	print('Trying to unlink db...')
	db.unlinkDb()
	print('unLink db success..')

@contextmanager
def userLoginCheck(db, name, passward):
	checkFunc = linkDb(db)
	yield checkFunc
	unlinkDb(db)
users = {'kite':'abc_12345', 'jim':'xyz@1345', 'tom':'hello_***'} #用户名和密码
db = myDb(users)

print('-----------------------------------------------------------')
userName = 'kite'
passWard = 'abc_12345'
with userLoginCheck(db, userName, passWard) as checkFunc:
	checkFunc(userName, passWard)
print('-----------------------------------------------------------')
userName = 'jim'
passWard = 'xyz@1346'
with userLoginCheck(db, userName, passWard) as checkFunc:
	checkFunc(userName, passWard)
'''
执行结果:
-----------------------------------------------------------
Trying to link to db...
Link db success..
kite Login success
Trying to unlink db...
unLink db success..
-----------------------------------------------------------
Trying to link to db...
Link db success..
jim Login fail
Trying to unlink db...
unLink db success..
'''



  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
The @contextmanager decorator in Python allows you to create a context manager using a generator function. A context manager is a class or function that is used to manage resources, such as opening and closing a file or acquiring and releasing a lock. The @contextmanager decorator provides a simple and concise way to create a context manager without having to define a class. The decorator takes a generator function as input and returns a context manager. The generator function must yield exactly once to indicate the beginning of the context and again at the end to indicate the end of the context. Any code inside the with statement will be executed within the context. Here is an example of a context manager created using the @contextmanager decorator: ```python from contextlib import contextmanager @contextmanager def open_file(file_path): file = open(file_path, 'w') try: yield file finally: file.close() with open_file('test.txt') as f: f.write('Hello, world!') ``` In this example, the open_file() function is decorated with @contextmanager. The function opens a file for writing and yields the file object. The try-finally block ensures that the file is closed properly when the context is exited. The with statement is used to create a context in which the file is opened and used to write a string to the file. When the with block is exited, the file is closed automatically. The @contextmanager decorator is a useful tool for creating context managers in a concise and readable manner.

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值