在C中,我可以将log printf放在这样的函数中:
void xx_lock (int xx_flag)
{
printf ("%s: START with %d\n", __FUNCTION__, xx_flag);
}
所以我可以在任何函数中复制我需要的同一行,并在日志中显示函数名称。我想在Python中使用类似的东西。但是,如果我使用
__name__
同样,它显示模块名称,而不是函数名称。
def xxx_lock(xx_flag=0)
sys.stdout.write("%s: START with %d\n" % (__name__, xx_flag))
我是否可以在该示例中使用一些简单的构造来显示Python函数名称?产生这样的输出:
xxx_lock: START with 1
已编辑:已将参数添加到示例中。
答案 0 :(得分:9)
你所要求的是无法做到的(很好 - 有办法,但它们是讨厌的黑客)。但是:你真的不想这样做。在更高层次上思考:您需要一种简单的方法来修改函数以记录它已经启动。更改函数的源代码并不是一个好方法 - 毕竟,日志记录与函数正在做的事情无关!相反,您想要修改事件事后。
def startLog( func ):
def loggedFunc( *args, **kwargs ):
print( "starting {0} with {1}".format( func.__name__, args[ 0 ] ) )
return func( *args, **kwargs )
return loggedFunc
@startLog
def theFunc( ):
print( "running theFunc" )
theFunc( )
# starting theFunc
# running theFunc
这是Python 装饰器的一个示例:它将define-time中的函数转换为另一个函数。这是语法糖:
def theFunc( ):
print( "running theFunc" )
theFunc = startLog( theFunc )
换句话说,你正在使用函数对象本身(记住 - 函数也是对象,你可以传递它们,修改它们,查看它们的属性等等)并重新定义它。查看源代码,我们看到startLog
定义了一个新函数(loggedFunc
),它首先打印一个日志跟踪,然后运行原始函数,并通过其参数。应用装饰器会将theFunc
替换为loggedFunc
,以便绑定到名称theFunc
的函数现在自行记录!
这有意义吗?我很乐意更详细地解释它。
正如已经指出的那样,这并没有具体回答你的问题;如果您需要更多功能,请使用logging
模块,它可以完成您需要的所有功能,然后使用一些功能。走堆栈只是icky,而且脆弱,但= p。
答案 1 :(得分:7)
import logging, sys logging.basicConfig(format="%(filename)s:%(funcName)s:%(message)s",level=logging.DEBUG,stream=sys.stderr) def testFunc(): logging.debug("entering") testFunc()
答案 2 :(得分:2)
import inspect
inspect.getframeinfo(inspect.currentframe()).function
这提供了最类似C的__FUNCTION__的功能,但正如katrielalex所说,它是一个黑客。装饰者最终是更好的解决方案。
答案 3 :(得分:1)
import inspect
def function_with_line(depth=1):
stack = inspect.stack()
frame = stack[depth][0]
code = frame.f_code
return "%s:%i" % (code.co_name, frame.f_lineno)
def foo():
print "Currently in %s" % function_with_line()
我不建议从高级代码中使用它;将其嵌入记录器并增加depth
以获取正确堆栈帧的名称。另请注意,此信息不会在Python的所有实现中提供。在Python的某些实现中,这也可能相当慢;如果记录性能对您很重要,请进行适当的基准测试。
你可能最好使用logging
,但如果由于某种原因这不是一个选项(例如,集成到另一个现有的日志系统中),那就是如何做到的。
答案 4 :(得分:0)
<sys._getframe( ).f_code.co_name>
完成了工作。
您的代码应如下所示:
import sys
def xxx_lock(xx_flag=0):
sys.stdout.write("%s: START with %d\n" % sys._getframe( ).f_code.co_name, xx_flag))