KBD

Keith Devens .com

Friday, December 5, 2008 Flag waving
This is not The Greatest Song in the World, oh no. This is just a tribute. – Tenacious D
← Program like you're under attackI think I've pissed off Google →

Daily link icon Saturday, October 4, 2003

Call a function from a string in Python

Hey, can anyone tell me how to call a function given a string containing that function's name in Python? It's very easy to do in languages like PHP or Perl: "$foo = 'funcname'; $foo()", but in Python I haven't found a way to do it. The apply() built-in doesn't take strings, for instance.

Hmm... after thinking about it for a bit, it's really not necessary that I be able to do this, but I'm still wondering if it's possible. Furthermore, is it possible to get a list of defined functions?

← Program like you're under attackI think I've pissed off Google →

Comments XML gif

Patrick Lioi (http://patrick.lioi.net) wrote:

I call member functions from strings in XMLTemplate using hasattr and getattr. For non-member functions, you might be able to use the same functions on the module object. Use like this (underscores for indentation):

if hasattr(obj, methodname):
_ member = getattr(obj, methodname)
_ member(args)

∴ Patrick Lioi | 4-Oct-2003 5:14pm est | http://patrick.lioi.net | #3022

Keith (http://keithdevens.com/) wrote:

Hmm... I'll have to think about that more, thanks.

While I have you, I have to ask: How'd you color your Python source code? Also, since you have a link to me on your site, would you mind correcting the spelling of my first name? Smiley winking

Keith | 4-Oct-2003 5:30pm est | http://keithdevens.com/ | #3023

Patrick Lioi (http://patrick.lioi.net) wrote:

Ack! You'd think with a last name like mine (I've seen it written as Lion, Leon, Lio, Loi...), I'd be more careful with people's names, but no. Smiley

I pass my code through codepaste for the syntax coloring.

∴ Patrick Lioi | 4-Oct-2003 5:54pm est | http://patrick.lioi.net | #3024

Simon Willison (http://simon.incutio.com/) wrote:

I've been using the functions globals() and locals() for this. They return a dictionary of all global and all local items respectively, where the key for each entry is the string name of that item and the value is the actual object. So to call a function called 'myfunc' in the local namespace you can do:

result = locals()['myfunc']()

∴ Simon Willison | 5-Oct-2003 5:44am est | http://simon.incutio.com/ | #3027

Keith (http://keithdevens.com/) wrote:

Exactly what I wanted! Thanks Simon. I'm also interested in Patrick's suggestion about module-level names -- I don't know where to get a handle on the current module, for instance. Names of methods within a class I already knew about.

Keith | 5-Oct-2003 6:00am est | http://keithdevens.com/ | #3028

J$ (http://alpha-geek.com) wrote:

Okay, in an earlier post, you mentioned [here -- ed.] coding as if your program is constantly under attack. Now, you want to invoke subroutines/methods/functions that are stored in a string var? In the world of Perl, you should be doing this with a hash instead (uhhh... I can't remember how to post code on your site without the formatting getting screwed up and it is not explained in the text above the post comment page and there is no preview comment functionality -- so this formatting may get screwy after I post it)

my $functionToCall = shift @ARGV; # or wherever it comes from
my %hash = ( thisString => &thisSub, thatString => &thisOtherSub );
die "no function to call" unless defined $hash{$functionToCall};
&$hash{$functionToCall};

# or, with args
$hash{$functionToCall}->('arg1', 'arg2',...);

I am not sure how to do this in Python, but I am sure there is a similar safe construct for that language, too.

∴ J$ | 7-Oct-2003 4:03pm est | http://alpha-geek.com | #3045

Keith (http://keithdevens.com/) wrote:

I'll fix the code for you Smiley

Whether it's safe or not depends on how you use it. I was mainly wondering if it's possible.

One example of safe usage is this: say you want to make every function in a module accessible over some RPC method, such as XML-RPC. Rather than having to store a reference to each function in a dict, you can simply call globals()[method](params) (or something) within the module.

Of course I'm not going to accept input from the outside world and call an arbitrary function based on that. That's a given.

Keith | 7-Oct-2003 7:34pm est | http://keithdevens.com/ | #3046

alf_chrono wrote:

You should try this:

def probe(args):
      return args + args ## 

args = 'Hello world'
string_funtion = 'list = ' + 'probe' + '(args)' 
exec string_funtion
print list ##print 'Hello worldHello world'

[fixed code formatting - ed]

∴ alf_chrono | 23-Feb-2004 10:45am est | #3981

Bob wrote:

Use eval() as shown below...

def calc(i,j):
return i + j

result = eval('calc')(2,4)

∴ Bob | 27-Feb-2004 4:13pm est | #4017

Chris C wrote:

The eval will work, but you don't want to use that.

1. There's a major performance hit as Python has to call the interpreter recursively. Using "locals()" or getattr is a simple dictionary lookup.

2. There's a major additional security risk, If the string is not properly cleansed, eval could call ANY python code, while a dictionary lookup could only result in a particular function in a particular scope from being called (which may or may not be safe).

It's far better to have a "name to function" mapping in a dictionary, as described above. OR, at the very least, force all function names to start with a series of characters, so that random functions could not be called.

∴ Chris C | 29-May-2008 4:55pm est | #10686

Patrick Corcoran wrote:

some_object.__getattribute__('method_name')()

is the same as:

some_object.method_name()
∴ Patrick Corcoran | 8-Oct-2008 3:53pm est | #10866

Feel free to post a comment below. Please see my comment policy.

Formatting Rules (No HTML):

  • **bold**, *italic*, _underlined_, --strikeout--
  • "text"="url" creates a link, and URLs are auto-highlighted
  • Blockquote: Like e-mail, begin paragraph with > (greater-than sign)
  • Lists: begin paragraph with *,-, or + (unordered), or # (ordered)
  • Code block: ?!code:language=perl|php|sql|javascript|etc.{\n}...{\n}?!/code

:
(will be your IP address if blank)
: (optional)
(Will not be shown on site)

: (optional)
:

December 2008
SunMonTueWedThuFriSat
 123456
78910111213
14151617181920
21222324252627
28293031 



RSS feed RSS feed for Keith's Weblog
Atom feed Atom feed for Keith's Weblog
Weblog archive
Recent comments
  on 4 posts

Recent comments XML

Girls, please don't get breast implants

I have 34 A breast but at 22 years​old they seem to be growing again​which ...

76.64.120.153: Dec 3, 10:00am

Perl 6 1.0 in March?

Doh, my mistake. I'm aware of the​relation between Parrot and Rakudo​but I'...

Keith: Dec 2, 1:03am

Free image hosting sites

Well, TinyPic has this in its​FAQ:

> Images and videos is in​your accoun...

Keith: Dec 1, 1:13am

Join a NameValueCollection into a querystring in C#

Well with a lamba expression, this​is what I came up​with:

?!code:csharp...

Gustaf Lindqvist: Nov 30, 4:38pm

Generated in about 0.204s.

(Used 8 db queries)

mobile phone