我想记录很多指标,例如执行函数需要多长时间。我希望解决方案是轻量级的。添加装饰器并完成。也许90%的时间都是这样的:
@LogMetrics
def my_business_logic(var1):
metrics.inc_counter('counter_a')
print 'done'
但是,我也希望能够访问指标对象并在10%的时间内执行此类操作:
class LogMetrics(object):
def __init__(self, module=None):
self.module = module
def __call__(self, target):
def wrapped(*args, **kwargs):
# set up metrics
metrics = Metrics(module=module)
metrics.start_timer()
try:
result = target(*args, **kwargs)
except Exception as e:
metrics.set_fault()
raise e
finally:
metrics.stop_timer()
metrics.push()
return result
return wrapped
到目前为止,我有一个处理第一个场景的装饰器:
keywords = ET.Element('keywords')
for string_ in strings: # < -- your strings
string = ET.SubElement(keywords, 'string')
string.text = string_
ET.dump(keywords)
如何支持方案2?我想做这样的事情answer,但共识似乎不是这样做的。请帮忙......
答案 0 :(得分:1)
唯一不涉及全局对象或禁止魔法的解决方案是将您的度量对象作为可选参数传递给您的函数(我假设如果您可以编辑它,那么您可以更改它签名):
class LogMetrics(object):
...
def __call__(self, target):
def wrapped(*args, **kwargs):
# set up metrics
metrics = Metrics(module=module)
kwargs['metrics'] = metrics # add metrics object to kwargs
metrics.start_timer()
try:
result = target(*args, **kwargs)
except Exception as e:
metrics.set_fault()
raise e
finally:
metrics.stop_timer()
metrics.push()
return result
return wrapped
@LogMetrics
def my_business_logic(var1, metrics=None):
if metrics is not None:
metrics.inc_counter('counter_a')
print 'done'
顺便说一下,您确定要在Metrics
内而不是wrapped
内初始化__call__
吗?
答案 1 :(得分:0)
您可以向函数添加属性。我做了一个非常简单的例子(在Python3中)。 display: none
装饰器会向原始函数添加add_counter
属性(您将添加_counter
对象)。每次调用后,此示例中的计数器都会递增。最后,在装饰函数中添加metrics
属性以允许访问计数器。
_orig_func