【发布时间】:2014-12-24 00:51:58
【问题描述】:
我正在尝试根据函数范围内的logging.Logger 实例的相应方法生成一堆函数。我感兴趣的功能/方法是:
['debug', 'info', 'warning', 'error', 'critical', 'exception']
它们都共享相同的原型。
现在我可以明确地说:
global debug, info, warning, error critical, exception
然后继续def 他们每个人。我检查了它,它工作正常。问题是我必须重复自己。
所以我有一个名为mylog 的logging.Logger 实例,它已经是一个全局变量。以下是我想要的,但通过分别硬编码函数/方法的名称:
global debug
def debug(msg, *args, **kwargs):
if mylog: mylog.debug(msg, *args, **kwargs)
为了简洁起见,我将只考虑debug 来编写我的示例,跳过其余部分。不幸的是,实际代码稍微复杂一些,因此使用lambda 的要求似乎没有得到满足(单条语句,对吗?)。
所以我的明显想法是在mylog 上使用getattr 和"debug" 的名称,然后简单地调用我在定义的函数中返回的任何内容,并将其按名称添加到globals() dict。示例:
for fct in ['debug']:
def x(msg, *args, **kwargs):
if mylog: getattr(mylog, fct)(msg, *args, **kwargs)
globals()[fct] = x
但我认为这实际上是不合法的,因为我将本应为类方法的方法称为静态方法。尽管如此,这“有效”,但每个输出行后面都有另一行说:None。
所以我想我可以将实例作为第一个参数传递。毕竟这就是self 的意义所在:
for fct in ['debug']:
def x(msg, *args, **kwargs):
if mylog: getattr(mylog, fct)(mylog, msg, *args, **kwargs)
globals()[fct] = x
这给了我:
TypeError: not all arguments converted during string formatting
这与我从中得到的效果相同:
for fct in ['debug']:
import types
def x(msg, *args, **kwargs):
if mylog: types.MethodType(getattr(mylog, fct), mylog)(msg, *args, **kwargs)
globals()[fct] = x
我基于这个问题的公认答案:Dynamically bind method to class instance in python
应用 Alex Martelli here 的答案会出现同样的错误。
我做错了什么?如何在不重复自己的情况下实现所需的行为?
完整的追溯:
Traceback (most recent call last):
File "/usr/lib64/python2.6/logging/__init__.py", line 776, in emit
msg = self.format(record)
File "/usr/lib64/python2.6/logging/__init__.py", line 654, in format
return fmt.format(record)
File "/usr/lib64/python2.6/logging/__init__.py", line 436, in format
record.message = record.getMessage()
File "/usr/lib64/python2.6/logging/__init__.py", line 306, in getMessage
msg = msg % self.args
TypeError: not all arguments converted during string formatting
完整的脚本,基于上面的第一个示例代码:
#!/usr/bin/env python
import sys, logging
def setup_logging():
global mylog
mylog = logging.getLogger('foobar')
mylog.addHandler(logging.StreamHandler())
for fct in ['debug']:
def x(msg, *args, **kwargs):
if mylog: getattr(mylog, fct)(mylog, msg, *args, **kwargs)
globals()[fct] = x
def main():
setup_logging()
debug('TEST LOG MESSAGE')
if __name__ == '__main__':
sys.exit(main())
【问题讨论】:
-
能否包含“并非所有参数”错误的完整回溯?
-
@NedBatchelder:不知道这会有什么帮助,因为这是在库模块中,但你去吧:)
标签: python logging dry python-2.6