Connecting Tech Pros Worldwide Forums | Help | Site Map

how to get name of function from within function?

Christopher J. Bottaro
Guest
 
Posts: n/a
#1: Jul 19 '05
I want to get the name of the function from within the function. Something
like:

def myFunc():
print __myname__[color=blue][color=green][color=darkred]
>>> myFunc()[/color][/color][/color]
'myFunc'

Really what I want to do is to easily strip off the prefix of a function
name and call another function. Like this:

def prefix_myFunc(a, b, c):
name = __myname__[7:]
call(name, a, b, c)

That would call myFunc(a, b, c).

How do I accomplish this 'elegantly', err...'pythonicly'..=)

Also, is there a way to turn normal positional args into a tuple without
using *? Like this:

def f(a, b, c):
print get_args_as_tuple()[color=blue][color=green][color=darkred]
>>> f(1, 2, 3)[/color][/color][/color]
(1, 2, 3)

I don't want to use
def f(*args):
print args
because I want to keep the error checking capability that comes with using a
fixed number of positional args.

Thank you for the help.


Steven Bethard
Guest
 
Posts: n/a
#2: Jul 19 '05

re: how to get name of function from within function?


Christopher J. Bottaro wrote:[color=blue]
> I want to get the name of the function from within the function. Something
> like:
>
> def myFunc():
> print __myname__
>[color=green][color=darkred]
>>>> myFunc()[/color][/color]
> 'myFunc'[/color]

There's not a really good way to do this. Can you give some more detail
on what exactly you're trying to do here? Depending on a function's
name within that function is probably a bad idea...

You *can* do this using a sys._getframe() hack:

py> def my_func():
.... print sys._getframe().f_code.co_name
....
py> my_func()
my_func

But that depends on a non-public API. Also, what do you want to happen
if someone binds another name to your function? The code above will
print the original name even if it's different from the new name(s):

py> g = my_func
py> del my_func
py> g()
my_func
py> my_func()
Traceback (most recent call last):
File "<interactive input>", line 1, in ?
NameError: name 'my_func' is not defined
[color=blue]
> Also, is there a way to turn normal positional args into a tuple without
> using *? Like this:
>
> def f(a, b, c):
> print get_args_as_tuple()
>[color=green][color=darkred]
>>>>f(1, 2, 3)[/color][/color]
>
> (1, 2, 3)[/color]

Um...

py> def f(a, b, c):
.... print (a, b, c)
....
py> f(1, 2, 3)
(1, 2, 3)

?

STeVe
Christopher J. Bottaro
Guest
 
Posts: n/a
#3: Jul 19 '05

re: how to get name of function from within function?


Steven Bethard wrote:
[color=blue]
> Christopher J. Bottaro wrote:[color=green]
>> I want to get the name of the function from within the function.
>> Something like:
>>
>> def myFunc():
>> print __myname__
>>[color=darkred]
>>>>> myFunc()[/color]
>> 'myFunc'[/color]
>
> There's not a really good way to do this. Can you give some more detail
> on what exactly you're trying to do here?[/color]

I want to make wrappers around functions but I can't use __getattr__ because
the functions are being published as a SOAP service and the SOAP lib I'm
using requires a callable object as the argument to the publishing
function.

Basically I want to wrap every function in try/except automatically.
Typically, I suppose people would do that with __getattr__. The way my
code is now is that every function (err, method) is enclosed in the exact
same try/except error handling code. Everytime I make a new function, I
copy/paste that try/catch block. Its ugly, it clutters the code, its prone
to error, and if i decide to change the error handling code later, I have
to change tons of functions.

Actually, I just realized that function call arguments are not passed to
__getattr__, so my idea of wrapping function calls that way won't work.

Is there something like PHP's __call() method in Python?
[color=blue][color=green]
>> Also, is there a way to turn normal positional args into a tuple without
>> using *? Like this:
>>
>> def f(a, b, c):
>> print get_args_as_tuple()
>>[color=darkred]
>>>>>f(1, 2, 3)[/color]
>>
>> (1, 2, 3)[/color]
>
> Um...
>
> py> def f(a, b, c):
> ... print (a, b, c)
> ...
> py> f(1, 2, 3)
> (1, 2, 3)
>
> ?[/color]

In your method, if the name and/or number of positional arguments changes,
the body of the function must change. I want to avoid that.

Thanks.

has
Guest
 
Posts: n/a
#4: Jul 19 '05

re: how to get name of function from within function?


Christopher J. Bottaro wrote:
[color=blue]
> Basically I want to wrap every function in try/except automatically.[/color]

Simplest way to do that would be something like:

def wrapFunction(func):
def wrapper(*args, **kargs):
try:
return func(*args, **kargs)
except Exception, e:
raise # your error handling code here
return wrapper

HTH

Steven Bethard
Guest
 
Posts: n/a
#5: Jul 19 '05

re: how to get name of function from within function?


Christopher J. Bottaro wrote:[color=blue]
> Basically I want to wrap every function in try/except automatically.[/color]
[snip][color=blue]
> every function (err, method) is enclosed in the exact
> same try/except error handling code. Everytime I make a new function, I
> copy/paste that try/catch block.[/color]

Yes, has's suggestion is probably the right way to go here. I'm still
uncertain as to your exact setup here. Are the functions you need to
wrap in a list you have? Are they imported from another module? A
short clip of your current code and what you want it to do would help.

For example, if they are the only thing another module contains, you can
use has's wrapFunction function and do something like:

import functionmodule

for name in dir(functionmodule):
if not name.startswith('_'):
func = wrapFunction(getattr(functionmodule, name))
setattr(functionmodule, name, func)
[color=blue]
> Is there something like PHP's __call() method in Python?[/color]

I don't know. What does PHP's __call() do? I don't know PHP, and it
wasn't in the online manual http://www.php.net/docs.php.
[color=blue][color=green][color=darkred]
>>>Also, is there a way to turn normal positional args into a tuple without
>>>using *? Like this:
>>>
>>>def f(a, b, c):
>>> print get_args_as_tuple()
>>>
>>>
>>>>>>f(1, 2, 3)
>>>
>>>(1, 2, 3)[/color]
>>
>>Um...
>>
>>py> def f(a, b, c):
>>... print (a, b, c)
>>...
>>py> f(1, 2, 3)
>>(1, 2, 3)
>>
>>?[/color]
>
> In your method, if the name and/or number of positional arguments changes,
> the body of the function must change. I want to avoid that.[/color]

But if the name and/or number of positional arguments changes, you're
already changing the function definition. What's the real use case
here? Are you really just printing them? Or are you doing something else?

STeVe
Christopher J. Bottaro
Guest
 
Posts: n/a
#6: Jul 19 '05

re: how to get name of function from within function?


Steven Bethard wrote:
[...snip...][color=blue]
> Yes, has's suggestion is probably the right way to go here. I'm still
> uncertain as to your exact setup here. Are the functions you need to
> wrap in a list you have? Are they imported from another module? A
> short clip of your current code and what you want it to do would help.[/color]

But I want to avoid having to write each wrapper myself. As it is now, when
I want to add a public method to my class named myFunc, I first write
myFunc which is a wrapper to the implementation:

def myFunc(self):
try: self.myFuncIMPL()
except: # error handling code

def myFuncIMPL(self):
# do the real stuff here, no need to worry about error handling stuff
# cuz its done in the wrapper

I guess I'm just lazy, but I don't want to write the wrapper func for each
new func I want to add. I want it done automatically.
[color=blue]
> I don't know. What does PHP's __call() do? I don't know PHP, and it
> wasn't in the online manual http://www.php.net/docs.php.[/color]

http://www.php.net/manual/en/languag...verloading.php

I haven't tried it yet, but this is what I would do with __call():

function __call($name, $args) {
$name .= 'IMPL';
try { $this->$name($args); }
except { # error handling; }
}

function funcA() {
# do something
}

function funcBIMPL($a, $b) {
# do something
}

So I imagine it would work like this:

$obj = new MyClass();
$obj->funcA(); # actually calls funcA because the function
# exists in the class
$obj->funcB($a, $b); # funcB doesn't exist, so __call() gets called with
# args 'funcB', array($a, $b)
# so inside __call(), we append 'IMPL' to $name, then invoke
# $this->funcBIMPL($a, $b)

Using this setup, when I want to add a new function called mySuperFunc(), I
merely have to define mySuperFuncIMPL() and magically the wrapper is "made
for me"...=)

Thanks for the help and ideas!

Andrew Dalke
Guest
 
Posts: n/a
#7: Jul 19 '05

re: how to get name of function from within function?


I'm with Steven Bethard on this; I don't know what you
(Christopher J. Bottaro) are trying to do.

Based on your example, does the following meet your needs?
[color=blue][color=green][color=darkred]
>>> class Spam(object):[/color][/color][/color]
.... def funcA(self):
.... print "A is called"
.... def __getattr__(self, name):
.... if name.startswith("_"):
.... raise AttributeError, name
.... f = get_function(name)
.... if f is not None:
.... return f
.... raise AttributeError, name
....[color=blue][color=green][color=darkred]
>>> def get_function(name):[/color][/color][/color]
.... return globals().get(name + "IMPL", None)
....[color=blue][color=green][color=darkred]
>>> x = Spam()
>>> x.funcA()[/color][/color][/color]
A is called[color=blue][color=green][color=darkred]
>>> x.funcB()[/color][/color][/color]
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 10, in __getattr__
AttributeError: funcB[color=blue][color=green][color=darkred]
>>> def funcBIMPL():[/color][/color][/color]
.... print "Calling all bees"
....[color=blue][color=green][color=darkred]
>>> x.funcB()[/color][/color][/color]
Calling all bees[color=blue][color=green][color=darkred]
>>>[/color][/color][/color]


Confused-ly-your's

Andrew
dalke@dalkescientific.com


Steven Bethard
Guest
 
Posts: n/a
#8: Jul 19 '05

re: how to get name of function from within function?


Christopher J. Bottaro wrote:[color=blue]
> I haven't tried it yet, but this is what I would do with __call():
>
> function __call($name, $args) {
> $name .= 'IMPL';
> try { $this->$name($args); }
> except { # error handling; }
> }
>
> function funcA() {
> # do something
> }
>
> function funcBIMPL($a, $b) {
> # do something
> }
>
> So I imagine it would work like this:
>
> $obj = new MyClass();
> $obj->funcA(); # actually calls funcA because the function
> # exists in the class
> $obj->funcB($a, $b); # funcB doesn't exist, so __call() gets called with
> # args 'funcB', array($a, $b)
> # so inside __call(), we append 'IMPL' to $name, then invoke
> # $this->funcBIMPL($a, $b)
>
> Using this setup, when I want to add a new function called mySuperFunc(), I
> merely have to define mySuperFuncIMPL() and magically the wrapper is "made
> for me"...=)[/color]

Something like this might work:

py> class C(object):
.... def func_a(self):
.... print "func_a"
.... def func_b_impl(self):
.... print "func_b"
.... raise Exception
.... def __getattr__(self, name):
.... func = getattr(self, '%s_impl' % name)
.... wrapped_func = self._impl_wrapper(func)
.... setattr(self, name, wrapped_func)
.... return wrapped_func
.... def _impl_wrapper(self, func):
.... def wrapper(*args, **kwargs):
.... try:
.... return func(*args, **kwargs)
.... except:
.... print "entered except"
.... raise
.... return wrapper
....
py> c = C()
py> c.func_a()
func_a
py> c.func_b()
func_b
entered except
Traceback (most recent call last):
File "<interactive input>", line 1, in ?
File "<interactive input>", line 15, in wrapper
File "<interactive input>", line 6, in func_b_impl
Exception

The idea here is that __getattr__ is called whenever the class doesn't
have a particular function. The __getattr__ method then tries to find a
corresponding _impl function, wraps it with appropriate try/except code,
and returns the wrapped function.

HTH,

STeVe
Raymond Hettinger
Guest
 
Posts: n/a
#9: Jul 19 '05

re: how to get name of function from within function?


[Christopher J. Bottaro][color=blue][color=green]
>> def myFunc():
>> print __myname__[color=darkred]
>> >>> myFunc()[/color]
>> 'myFunc'[/color][/color]

Perhaps the __name__ attribute is what you want:

[color=blue][color=green][color=darkred]
>>> def myFunc():[/color][/color][/color]
print myFunc.__name__
[color=blue][color=green][color=darkred]
>>> myFunc()[/color][/color][/color]
myFunc

Kent Johnson
Guest
 
Posts: n/a
#10: Jul 19 '05

re: how to get name of function from within function?


Christopher J. Bottaro wrote:[color=blue]
> Steven Bethard wrote:
> [...snip...]
>[color=green]
>>Yes, has's suggestion is probably the right way to go here. I'm still
>>uncertain as to your exact setup here. Are the functions you need to
>>wrap in a list you have? Are they imported from another module? A
>>short clip of your current code and what you want it to do would help.[/color]
>
>
> But I want to avoid having to write each wrapper myself. As it is now, when
> I want to add a public method to my class named myFunc, I first write
> myFunc which is a wrapper to the implementation:
>
> def myFunc(self):
> try: self.myFuncIMPL()
> except: # error handling code
>
> def myFuncIMPL(self):
> # do the real stuff here, no need to worry about error handling stuff
> # cuz its done in the wrapper
>
> I guess I'm just lazy, but I don't want to write the wrapper func for each
> new func I want to add. I want it done automatically.[/color]

You can do this almost automatically with a decorator:

def in_try(func):
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except:
print "entered except"
raise
return wrapper

class C(object):
@in_try
def func_a(self):
print "func_a"

@in_try
def func_b(self):
print "func_b"
raise Exception

You could probably create a metaclass to apply the wrappers automatically but I like having it explicit as above.

Kent
Christopher J. Bottaro
Guest
 
Posts: n/a
#11: Jul 19 '05

re: how to get name of function from within function?


<posted & mailed>

Hey again Steven,
I'm still having problems...

Steven Bethard wrote:
[color=blue]
> Something like this might work:
>
> py> class C(object):
> ... def func_a(self):
> ... print "func_a"
> ... def func_b_impl(self):
> ... print "func_b"
> ... raise Exception
> ... def __getattr__(self, name):
> ... func = getattr(self, '%s_impl' % name)
> ... wrapped_func = self._impl_wrapper(func)
> ... setattr(self, name, wrapped_func)
> ... return wrapped_func
> ... def _impl_wrapper(self, func):
> ... def wrapper(*args, **kwargs):
> ... try:
> ... return func(*args, **kwargs)
> ... except:
> ... print "entered except"
> ... raise
> ... return wrapper
> ...
> py> c = C()
> py> c.func_a()
> func_a
> py> c.func_b()
> func_b
> entered except
> Traceback (most recent call last):
> File "<interactive input>", line 1, in ?
> File "<interactive input>", line 15, in wrapper
> File "<interactive input>", line 6, in func_b_impl
> Exception
>
> The idea here is that __getattr__ is called whenever the class doesn't
> have a particular function. The __getattr__ method then tries to find a
> corresponding _impl function, wraps it with appropriate try/except code,
> and returns the wrapped function.[/color]

The problem is:[color=blue][color=green][color=darkred]
>>> c.func_b.__name__[/color][/color][/color]
'wrapper'

That messes up SOAPpy's RegisterFunction() method which apparently depends
on the __name__ of the function to publish it as an available SOAP
function.

Any suggestions on how to change the name of c.func_b to 'func_b' instead of
'wrapper'?
[color=blue]
> HTH,
> STeVe[/color]

Thanks a bunch,
-- C

Steven Bethard
Guest
 
Posts: n/a
#12: Jul 19 '05

re: how to get name of function from within function?


Christopher J. Bottaro wrote:[color=blue]
> Steven Bethard wrote:[color=green]
>>... def _impl_wrapper(self, func):
>>... def wrapper(*args, **kwargs):
>>... try:
>>... return func(*args, **kwargs)
>>... except:
>>... print "entered except"
>>... raise
>>... return wrapper
>>...[/color][/color]
[snip][color=blue]
>
> The problem is:
>[color=green][color=darkred]
>>>>c.func_b.__name__[/color][/color]
>
> 'wrapper'
>
> That messes up SOAPpy's RegisterFunction() method which apparently depends
> on the __name__ of the function to publish it as an available SOAP
> function.[/color]

Hmm... Nasty. If you were using Python 2.4, you could simply write it as:

def _impl_wrapper(self, func):
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except:
print "entered except"
raise
wrapper.__name__ = func.__name__
return wrapper

Where you fix up the wrapper's __name__ attribute. But I believe the
__name__ attribute is read-only in Python 2.3...

STeVe
Christopher J. Bottaro
Guest
 
Posts: n/a
#13: Jul 19 '05

re: how to get name of function from within function?


<posted & mailed>

Christopher J. Bottaro wrote:
[color=blue]
> The problem is:[color=green][color=darkred]
>>>> c.func_b.__name__[/color][/color]
> 'wrapper'
>
> That messes up SOAPpy's RegisterFunction() method which apparently depends
> on the __name__ of the function to publish it as an available SOAP
> function.
>
> Any suggestions on how to change the name of c.func_b to 'func_b' instead
> of 'wrapper'?[/color]

Nevermind, I looked at the SOAPpy source, they provide a way to manually
specify the SOAP method name that is published.

Thanks anyways,
-- C

Closed Thread