我有一個類C在一個大程式中到處實體化。C.__init__()包含除錯日志,將引數傳遞給新實體。
這些日志條目包含實體化C. 這可以使用traceback. 但是除錯日志陳述句的引數不應該有副作用,因為在實踐中它們幾乎總是無操作。那么如何才能實作呢?
uj5u.com熱心網友回復:
它可以用一個單例物件來完成,它的表示是它的呼叫者的名字(或者它的呼叫者的呼叫者,或者......):
logger.debug("new C instance, with a=%d, b=%d, called from %s",
a, b, show_caller)
然后是搜索呼叫堆疊多遠的問題:我們將不得不繞過日志庫中的幾層呼叫,以及呼叫我們的建構式。
我通過假設show_caller's 類存在于一個名稱與呼叫者的包相似的包中解決了這個問題。例如,它可能正在 wombat.spong.C呼叫wombat.util.ShowCaller. 該變數DEPTH給出了兩個應該共享的名稱。
這不是一個非常令人滿意的解決方案,但它確實有效。
所以我們有:
import os
class _ShowCaller:
"""
Singleton class whose representation names the caller of the caller.
The object of this class does nothing in particular most of the time.
But when you use it in the parameters of a logging statement, thus:
```
logger.debug("ready; was called from %s", show_caller)
```
it returns a string giving the name, filename, and line number
of the caller of the method containing the logging statement.
If this was done using a function call, the call would take place
every time the logging statement was executed, even in production
where it would be a no-op.
Attributes:
DEPTH (`int`): how many levels of directory we should consider
to be part of our package, rather than being library modules.
"""
DEPTH = 1
def __init__(self):
self.prefix = os.path.sep.join(
__file__.split(os.path.sep)[:-self.DEPTH]
)
def __repr__(self):
import traceback
stack = reversed(list(enumerate(traceback.extract_stack()[:-1])))
for i, caller in stack:
if caller.filename.startswith(self.prefix):
break
try:
i, caller = next(stack)
return '%s (%s:%s)' % (
caller.name,
caller.filename[len(self.prefix) 1:],
caller.lineno,
)
except StopIteration:
return '???'
show_caller = _ShowCaller()
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/460890.html
