print(exec_traceback) print("__exit__") with myContextManager() as f: raise IndexError 使用contextManager 装饰器实现 使用contextManager装饰器需要注意,必须要使用yield,yield前类似于__enter__,yield返回的对象就是__enter__返回的对象,yield后便是类似于__exit __的方法 @contextmanager def some_generator(<arguments>): <setup> try: yield <value>
@contextmanager 装饰器 learn from 《流畅的python》 1. else for/else、while/else 和 try/else 前两者 只有在 没有被break 时 例如,同时打开任意一个文件列表中的所有文件 使用最广泛的是 @contextmanager 装饰 器,因此要格外留心。 @contextmanager 装饰器 @contextmanager 装饰器能减少代码量,因为 不用编写一个完整的类,定义 __enter__ 和 __exit__ 方法,而 只需实现 有一个 yield 语句的生成器,生成想让 __enter__ 方法返回的值 在使用 @contextmanager 装饰的生成器中,yield 语句的作用是 把函数的定义体分成两部分: yield 语句前面的所有代码在 # DCBA print("Michael learning python") print(what) # Michael learning python # ABCD 其实,contextlib.contextmanager
_counter@contextmanager 装饰器解析除了定义类,还可以用装饰器 @contextmanager 来创建 context manager 。 当我们使用 @contextmanager 装饰一个生成器函数时,装饰器会:创建一个新的类,实现 __enter__ 和 __exit__ 方法将我们的生成器函数分成三部分:yield 之前的代码放入 enter__ 的返回值yield 之后的代码放入 __exit__例如:import osfrom contextlib import contextmanagerimport time# 方式1:使用 @contextmanager 测试 @contextmanager 装饰器版本:") try: with temp_file("test1.txt") as f: process_file( 测试 @contextmanager 装饰器版本:创建临时文件: test1.txt处理文件: test1.txt清理临时文件: test1.txt正常完成2.
>[] argumentsTypes, Throwable t) { ContextManager.activeSpan().errorOccurred().log(t); } ,并将ContextManager.capture()放入到ShardingExecuteDataMap.getDataMap()中;其afterMethod执行ContextManager.stopSpan ,并将ContextManager.capture()放入到ShardingExecuteDataMap.getDataMap()中;其afterMethod执行ContextManager.stopSpan 并设置DB_STATEMENT;其afterMethod方法执行ContextManager.stopSpan();其handleMethodException方法执行ContextManager.activeSpan (contextSnapshot);其afterMethod方法执行ContextManager.stopSpan();其handleMethodException方法执行ContextManager.activeSpan
3. contextlib.contextmanager 装饰器 标准库中,contextlib.contextmanager 装饰器通过 yield 关键字可以减少创建上下文管理器的样板代码量。 上面的例子可以改造为: import contextlib class Test: @contextlib.contextmanager def contextmanager(self import contextlib class Test: @contextlib.contextmanager def contextmanager(self): print 所以,在使用 @contextlib.contextmanager 时千万要注意,不能在 yield 执行时抛出异常。 import contextlib class Test: @contextlib.contextmanager def contextmanager(self): print
实现了InstanceConstructorInterceptor接口,其onConstruct方法将ContextManager.capture()设置给objInst的skyWalkingDynamicField = null) { ContextManager.stopSpan(); } return ret; } @Override >[] argumentsTypes, final Throwable t) { if (ContextManager.isActive()) { ,然后获取objInst.getSkyWalkingDynamicField(),若不为null则执行ContextManager.continued(contextSnapshot);其afterMethod 方法获取objInst.getSkyWalkingDynamicField(),若不为null则执行ContextManager.stopSpan();其handleMethodException方法执行
>[] argumentsTypes, Object ret) throws Throwable { if (ContextManager.getRuntimeContext().get ();其afterMethod方法执行ContextManager.getRuntimeContext().remove(Constants.SPRING_CLOUD_GATEWAY_TRANSMITTER (transmitter.getOperationName(), peer); ContextManager.continued(transmitter.getSnapshot( >[] argumentsTypes, Throwable t) { ContextManager.activeSpan().errorOccurred().log(t); } >[] argumentsTypes, Throwable t) { ContextManager.activeSpan().errorOccurred().log(t); }
>[] argumentsTypes, Throwable t) { ContextManager.activeSpan().errorOccurred().log(t); } >[] argumentsTypes, Object ret) throws Throwable { ContextManager.stopSpan(); >[] argumentsTypes, Throwable t) { ContextManager.activeSpan().errorOccurred().log(t); } >[] argumentsTypes, Throwable t) { ContextManager.activeSpan().errorOccurred().log(t); } } OnSuccessInterceptor实现了InstanceMethodsAroundInterceptor接口,其beforeMethod方法执行ContextManager.continued
>[] argumentsTypes, Throwable t) { ContextManager.activeSpan().errorOccurred().log(t); } >[] argumentsTypes, Object ret) throws Throwable { ContextManager.stopSpan(); >[] argumentsTypes, Throwable t) { ContextManager.activeSpan().errorOccurred().log(t); } >[] argumentsTypes, Throwable t) { ContextManager.activeSpan().errorOccurred().log(t); } } OnSuccessInterceptor实现了InstanceMethodsAroundInterceptor接口,其beforeMethod方法执行ContextManager.continued
@contextmanager是一个装饰器decorator,它接收一个生成器generator,把generator里yield的值赋给with...as后的变量,然后正常执行with语句。 from contextlib import contextmanager class A(object): def print_hello(self): print('hello world') @contextmanager def B(): print('Start') a = A() yield a print('Over') with 通过@contextmanager,我们还能实现简单的运行前执行特定代码的功能: @contextmanager def tag(name): print("<%s>" % name) 装饰的一个生成器,它内部是这样的: @contextmanager def closing(thing): try: yield thing finally:
>[] argumentsTypes, Throwable t) { ContextManager.activeSpan().errorOccurred().log(t); } ,并将ContextManager.capture()放入到ShardingExecuteDataMap.getDataMap()中;其afterMethod执行ContextManager.stopSpan ,并将ContextManager.capture()放入到ShardingExecuteDataMap.getDataMap()中;其afterMethod执行ContextManager.stopSpan 并设置DB_STATEMENT;其afterMethod方法执行ContextManager.stopSpan();其handleMethodException方法执行ContextManager.activeSpan (contextSnapshot);其afterMethod方法执行ContextManager.stopSpan();其handleMethodException方法执行ContextManager.activeSpan
()) { allArguments[0] = new SWCallable((Callable) allArguments[0], ContextManager.capture (snapshot); return callable.call(); } catch (Exception e) { ContextManager.activeSpan ().errorOccurred().log(e); throw e; } finally { ContextManager.stopSpan (); } } } SWCallable实现了Callable接口,其call方法在执行callable.call()之前先ContextManager.createLocalSpan ,然后执行ContextManager.continued(snapshot),之后在catch异常里头执行ContextManager.activeSpan().errorOccurred().log
= EXPR VAR = ContextManager. 退出 并得到了一个写了 Hello 的 file.txt 文件 通过try/finally语句执行: ContextManager = File('file.txt', 'w') VAR = ContextManager 五、contextmanager 装饰器 Python还提供了一个contextmanager装饰器,允许用户将一个生成器定义为上下文管理器,该装饰器将生成器中的代码通过yield语句分成两部分,yield 下面我们通过contextmanager装饰器也实现一个关于文件的上下文管理器: from contextlib import contextmanager @contextmanager def open_file ,其实稍微想想就知道,肯定是contextmanager装饰器把生成器加工成一个内部实现了__enter__和__exit__方法的对象,有时间的话另写一篇文章带大家看看contextmanager的源码
>[] argumentsTypes, Object ret) throws Throwable { if (ContextManager.getRuntimeContext().get ();其afterMethod方法执行ContextManager.getRuntimeContext().remove(Constants.SPRING_CLOUD_GATEWAY_TRANSMITTER (transmitter.getOperationName(), peer); ContextManager.continued(transmitter.getSnapshot( >[] argumentsTypes, Throwable t) { ContextManager.activeSpan().errorOccurred().log(t); } >[] argumentsTypes, Throwable t) { ContextManager.activeSpan().errorOccurred().log(t); }
实现了InstanceConstructorInterceptor接口,其onConstruct方法将ContextManager.capture()设置给objInst的skyWalkingDynamicField = null) { ContextManager.stopSpan(); } return ret; } @Override >[] argumentsTypes, final Throwable t) { if (ContextManager.isActive()) { ,然后获取objInst.getSkyWalkingDynamicField(),若不为null则执行ContextManager.continued(contextSnapshot);其afterMethod 方法获取objInst.getSkyWalkingDynamicField(),若不为null则执行ContextManager.stopSpan();其handleMethodException方法执行
()) { allArguments[0] = new SWCallable((Callable) allArguments[0], ContextManager.capture (snapshot); return callable.call(); } catch (Exception e) { ContextManager.activeSpan ().errorOccurred().log(e); throw e; } finally { ContextManager.stopSpan (); } } } SWCallable实现了Callable接口,其call方法在执行callable.call()之前先ContextManager.createLocalSpan ,然后执行ContextManager.continued(snapshot),之后在catch异常里头执行ContextManager.activeSpan().errorOccurred().log
装饰器简化代码:python1from contextlib import contextmanager23@contextmanager4def db_connection(dsn):5 conn @contextmanager5def timer(name="Operation"):6 start = time.time()7 try:8 yield9 finally 上下文管理器可避免忘记释放锁:python1import threading2from contextlib import contextmanager34lock = threading.Lock() 56@contextmanager7def locked(lock_obj):8 lock_obj.acquire()9 try:10 yield11 finally:12 resource_a():5 print("获取资源A")6 yield "A"7 print("释放资源A")89@contextmanager10def resource_b()
通过 ContextManager#createEntrySpan、 ContextManager#createLocalSpan、 ContextManager#createExistSpan 等方法来创建一个 管理的 ThreadLocal ContextManager.CONTEXT 中。 因为 ContextManager 使用 ThreadLocal 来维持 TracerContext, 那么在一次调用事务链中每次创建 Span , 可能对应不同的 TracerContext. 在实现异步框架的插件时, 当创建第一个 Span 后, 需要使用 ContextManager.capture() 获取到 ContextSnapshot, 并放置到异步框架本身的上下文来传递。 来恢复上下文 AbstractSpan span = ContextManager.createExitSpan(operationName, contextCarrier, remotePeer
>[] argumentsTypes, Object ret) throws Throwable { ContextManager.stopSpan >[] argumentsTypes, Throwable t) { ContextManager.activeSpan().errorOccurred().log(t); } ();handleMethodException方法则执行ContextManager.activeSpan().errorOccurred().log(t) EndTransactionMethodInterceptor >[] argumentsTypes, Object ret) throws Throwable { ContextManager.stopSpan >[] argumentsTypes, Throwable t) { ContextManager.activeSpan().errorOccurred().log(t); }
enter from Cat named Harry hello, Tom hello, Harry exit from Cat named Harry exit from Cat named Tom 3、contextmanager python提供了contextlib.contextmanager 让我们重写上面的例子,使用contextmanager from contextlib import contextmanager as _contextmanager @_contextmanager def cat(name): print 'enter cat named %s' % name yield as _contextmanager # 简单创建redis的客户端 r = redis.Redis(host='localhost', port=6379, db=0) # 分布式锁实现 # finally 中验证本线程是否获得锁, 是为了防止误删别的线程获取的锁 @_contextmanager def dist_lock(client, key): dist_lock_key = 'lock:%