how to get name of function from within function?

  • Thread starter Christopher J. Bottaro
  • Start date
C

Christopher J. Bottaro

I want to get the name of the function from within the function. Something
like:

def myFunc():
print __myname__'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()(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.
 
S

Steven Bethard

Christopher said:
I want to get the name of the function from within the function. Something
like:

def myFunc():
print __myname__

'myFunc'

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


(1, 2, 3)

Um...

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

?

STeVe
 
C

Christopher J. Bottaro

Steven said:
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?

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?
Um...

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

?

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.
 
H

has

Christopher said:
Basically I want to wrap every function in try/except automatically.

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
 
S

Steven Bethard

Christopher said:
Basically I want to wrap every function in try/except automatically. [snip]
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.

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)
Is there something like PHP's __call() method in Python?

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.
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.

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
 
C

Christopher J. Bottaro

Steven Bethard wrote:
[...snip...]
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.

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.
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.

http://www.php.net/manual/en/language.oop5.overloading.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!
 
A

Andrew Dalke

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?
.... 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
.... .... return globals().get(name + "IMPL", None)
.... Traceback (most recent call last):
File "<stdin>", line 1, in ?
.... print "Calling all bees"
....

Confused-ly-your's

Andrew
(e-mail address removed)
 
S

Steven Bethard

Christopher said:
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"...=)

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
 
R

Raymond Hettinger

[Christopher J. Bottaro]
Perhaps the __name__ attribute is what you want:

print myFunc.__name__
myFunc
 
K

Kent Johnson

Christopher said:
Steven Bethard wrote:
[...snip...]
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.


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.

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
 
C

Christopher J. Bottaro

Steven Bethard wrote:

....snip...
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,

Yes, it does! Thats perfect, and it works with Python 2.3 (which I'm
using). Thank you very much.

-- C
 
C

Christopher J. Bottaro

Kent Johnson wrote:

....snip...
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.

Another good solution, thank you. Maybe a reason to upgrade to 2.4...=)

-- C
 
S

Steven Bethard

Christopher said:
Another good solution, thank you. Maybe a reason to upgrade to 2.4...=)

If you can't upgrade, you can write Kent's code like:

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

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

STeVe
 
C

Christopher J. Bottaro

Steven said:
If you can't upgrade, you can write Kent's code like:

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

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

Yup, @ is shorthand for rebinding the function after applying the arg(s). I
actually know this stuff, I wonder why I can't think of it on my own...ugh.
Guess I gotta practice my knowledge more often.

Thanks for the tip,
-- C
 
C

Christopher J. Bottaro

<posted & mailed>

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

Steven said:
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.

The problem is:'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'?
HTH,
STeVe

Thanks a bunch,
-- C
 
S

Steven Bethard

Christopher said:
Steven said:
... def _impl_wrapper(self, func):
... def wrapper(*args, **kwargs):
... try:
... return func(*args, **kwargs)
... except:
... print "entered except"
... raise
... return wrapper
...
[snip]

The problem is:

'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.

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
 
C

Christopher J. Bottaro

<posted & mailed>
The problem is:
'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'?

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

Thanks anyways,
-- C
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top