如何在Python中实现与C语言的__FUNCTION__相同的功能?
在C语言中,我可以在一个函数里放一个日志打印,比如这样:
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
编辑:我在例子中添加了参数。
5 个回答
import inspect
inspect.getframeinfo(inspect.currentframe()).function
这个方法提供的功能最像C语言中的__FUNCTION__,不过正如katrielalex所说,这其实是一种变通的做法。最终,使用装饰器会是更好的解决方案。
你问的这个问题其实是没法做到的(好好地做到是没办法的——有些方法可以实现,但都是些很糟糕的技巧)。不过,你其实不想这样做。换个角度想:你想要一个简单的方法来修改一个函数,让它在开始时记录日志。直接改这个函数的源代码并不是个好办法——毕竟,记录日志和这个函数的实际工作没什么关系!相反,你应该在函数执行后再进行修改。
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的装饰器示例:它在定义时把一个函数转换成另一个函数。这其实是更简洁的写法,等于:
def theFunc( ):
print( "running theFunc" )
theFunc = startLog( theFunc )
换句话说,你是在直接操作这个函数对象(记住——函数也是对象,你可以传递它们、修改它们、查看它们的属性等等!),然后重新定义它。看源代码,我们可以看到startLog
定义了一个新函数(loggedFunc
),这个新函数首先打印一条日志,然后再运行原来的函数,并把参数传递给它。使用这个装饰器后,theFunc
就被替换成了loggedFunc
,所以现在绑定到theFunc
这个名字的函数会自己记录日志了!
这样说清楚了吗?如果需要,我可以更详细地解释。
补充
正如之前提到的,这个回答并没有直接解决你的问题;如果你需要更多功能,可以使用logging
模块,它能满足你所有的需求,甚至更多。遍历调用栈的做法既麻烦又不稳定,真的不推荐哦 =p。
katrielalex说得对,你不应该尝试用“C语言”的方式来做这件事。Python自带了很多功能,那为什么不直接使用这些功能呢?
import logging, sys logging.basicConfig(format="%(filename)s:%(funcName)s:%(message)s",level=logging.DEBUG,stream=sys.stderr) def testFunc(): logging.debug("entering") testFunc()