开发者

How do I get the same functionality as C's __FUNCTION__ in Python?

In C, I can put a log printf inside a function like this:

void xx_lock (int xx_flag)
{
  printf ("%s: START with %d\n", __FUNCTION__, xx_flag);
}

so I can copy the same line where I need in any function and it displays the function name in the log. I want something similar in Python. But if I use

__name__

the same way, it displays the module name, not the function开发者_开发知识库 name.

def xxx_lock(xx_flag=0)
    sys.stdout.write("%s: START with %d\n" % (__name__, xx_flag))

Is there some simple construct that I can use in that example to show the Python function name? To produce output like this:

xxx_lock: START with 1

Edited: added the parameter to the example.


What you've asked for can't be done (nicely -- there are ways of doing it but they are nasty hacks). BUT: you don't really want to do that. Think at a higher level: you want an easy way to modify a function to log that it has started. Changing the source code of the function isn't a good way do to that -- after all, the logging has nothing to do with what the function is doing! Instead, you want to modify the function ex post facto.

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

This is an example of a Python decorator: it transforms a function at define-time into another one. It's syntactic sugar for:

def theFunc( ):
    print( "running theFunc" )
theFunc = startLog( theFunc )

In other words, you are taking the function object itself (remember -- functions are objects too, you can pass them around, modify them, look at their attributes, etc!) and redefining it. Looking at the source code, we see that startLog defines a new function (loggedFunc), which first prints a log trace and then runs the original function, passing through its arguments. Applying the decorator replaces theFunc with loggedFunc, so that the function bound to the name theFunc now logs itself!

Does that make sense? I'm happy to explain it in more detail.

Edit

As has been pointed out, this doesn't specifically answer your question; if you need any more functionality than this then use the logging module which does everything you'll ever need and then some. Walking the stack is just icky, as well as fragile, though =p.


katrielalex above is right that you should not attempt to do this the "C way". Python has batteries included, so why not use them?

import logging, sys

logging.basicConfig(format="%(filename)s:%(funcName)s:%(message)s",level=logging.DEBUG,stream=sys.stderr)

def testFunc():
    logging.debug("entering")

testFunc()


import inspect
inspect.getframeinfo(inspect.currentframe()).function

This provides the functionality that most resembles C's __FUNCTION__, but as katrielalex said, it is a hack. The decorator is the better solution in the end.


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()

I don't recommend using this from high-level code; embed it in the logger and increase depth to get the name of the correct stack frame. Also, be aware that this information won't be available in all implementations of Python. This may also be fairly slow in some implementations of Python; if logging performance matters to you, benchmark appropriately.

You're probably best off using logging, but if that's not an option for some reason (eg. integrating into another existing logging system), that's how to do it.


<sys._getframe( ).f_code.co_name> does the job.

Your code should be like this:

import sys

def xxx_lock(xx_flag=0):
    sys.stdout.write("%s: START with %d\n" % sys._getframe( ).f_code.co_name, xx_flag))
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜