如何在Python中获得与C的__FUNCTION__相同的功能?

时间:2010-08-06 15:55:48

标签: python function

在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

已编辑:已将参数添加到示例中。

5 个答案:

答案 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)

上面的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()

答案 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))