Keith Devens .com |
Friday, December 5, 2008 | ![]() |
| This is not The Greatest Song in the World, oh no. This is just a tribute. – Tenacious D | ||
|
| ← Program like you're under attack | I think I've pissed off Google → |

Patrick Lioi (http://patrick.lioi.net) wrote:
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? 
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. 
I pass my code through codepaste for the syntax coloring.
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']()
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.
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.
Keith (http://keithdevens.com/) wrote:
I'll fix the code for you 
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.
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]
Bob wrote:
Use eval() as shown below...
def calc(i,j):
return i + j
result = eval('calc')(2,4)
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.
Patrick Corcoran wrote:
some_object.__getattribute__('method_name')()
is the same as:
some_object.method_name()
Feel free to post a comment below. Please see my comment policy.
Formatting Rules (No HTML):
Generated in about 0.204s.
(Used 8 db queries)

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)