Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 597
codebunny Avatar asked Aug 06 '10 15:08

codebunny


People also ask

What is__ class__ in Python?

__class__ is an attribute on the object that refers to the class from which the object was created. a. __class__ # Output: <class 'int'> b. __class__ # Output: <class 'float'> After simple data types, let's now understand the type function and __class__ attribute with the help of a user-defined class, Human .

What is __ module __ in Python?

A module in Python is a file (ending in .py ) that contains a set of definitions (variables and functions) that you can use when they are imported. Modules are considered as objects, just as everything else is in Python.

How do I find the built-in function in Python?

Check with the built-in function dir() The built-in function dir() returns a list of names of attributes, methods, etc. of the object specified in the argument. You can get a list of names of built-in objects, such as built-in functions and constants, by passing the builtins module or __builtins__ to dir() .


2 Answers

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.

like image 172
Katriel Avatar answered Oct 04 '22 05:10

Katriel


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()
like image 34
loevborg Avatar answered Oct 04 '22 05:10

loevborg