I have a str object for example: menu = 'install'
. I want to run install method from this string. For example when I call menu(some, arguments)
it will call install(some, arguments)
. Is there any way to do that ?
Asked
Active
Viewed 1.5e+01k times
112

Julien
- 13,986
- 5
- 29
- 53

İlker Dağlı
- 1,593
- 3
- 13
- 10
-
I changed the duplicate link because https://stackoverflow.com/questions/3061/ is narrowly scoped; this question is looking for `install` in an unspecified namespace (but probably intended to be either the local or global namespace), not as an attribute of a module. – Karl Knechtel Jul 06 '22 at 23:12
3 Answers
152
If it's in a class, you can use getattr:
class MyClass(object):
def install(self):
print "In install"
method_name = 'install' # set by the command line options
my_cls = MyClass()
method = None
try:
method = getattr(my_cls, method_name)
except AttributeError:
raise NotImplementedError("Class `{}` does not implement `{}`".format(my_cls.__class__.__name__, method_name))
method()
or if it's a function:
def install():
print "In install"
method_name = 'install' # set by the command line options
possibles = globals().copy()
possibles.update(locals())
method = possibles.get(method_name)
if not method:
raise NotImplementedError("Method %s not implemented" % method_name)
method()

Sam Dolan
- 31,966
- 10
- 88
- 84
-
1Thank you for your answer. But what if the method is not in a class? – İlker Dağlı Oct 29 '11 at 02:23
-
Thank you so much sdolan. I have tried with **globals** not **locals** and it works. – İlker Dağlı Oct 29 '11 at 02:31
-
6The latter does not .copy() globals before mutating it, inviting all sorts of trouble. And it has a bug, since it calls the method immediately before checking it, then calls its result again. Also, it's common practise to use a prefix, to prevent calling just ANY element in the namespace (e.g. "do_install()"). – pyroscope Oct 29 '11 at 05:18
-
@pyroscope: Good catch on the globals. I've updated the sample code to do that. I also agree on the prefix, and do that in my own code where it makes sense. I don't know the specifics of the OPs problem, so I'm trying to not jump to any conclusions. – Sam Dolan Oct 30 '11 at 02:27
-
@sdolan , Perfect answer but a minor mistake getattr does not respond with None if attribute does not exista rather it raises an exception so **if not method: raise Exception("Method %s not implemented" % method_name)** is not needed – Sarath Sadasivan Pillai Feb 09 '16 at 10:56
-
@Sarathsp: haha good catch. Only took 4.5 years for someone to catch it ;) – Sam Dolan Feb 20 '16 at 20:31
-
And if you are sure that method exists, you can use: globals().get(method_name)() or locals().get(method_name)() – Alex Benfica Apr 24 '16 at 11:38
-
Your first answer: raise NotImplementedError("Class `{}` does not implement `{}`".format(my_cls.__class__.__name__, method_name) Should be: raise NotImplementedError("Class `{}` does not implement `{}`".format(my_cls.__class__.__name__, method_name)) – Mo Ali Jan 18 '17 at 19:30
-
-
@AlexBenfica what's the difference between calling by globals and locals? – Nihat Aug 17 '20 at 11:35
-
1@Nihat please refer to this question. https://stackoverflow.com/questions/7969949/whats-the-difference-between-globals-locals-and-vars – Alex Benfica Aug 17 '20 at 19:39
-
76
You can use a dictionary too.
def install():
print "In install"
methods = {'install': install}
method_name = 'install' # set by the command line options
if method_name in methods:
methods[method_name]() # + argument list of course
else:
raise Exception("Method %s not implemented" % method_name)

concentricpuddle
- 777
- 5
- 11
-
11I believe using dictionary is a bit more clean that relying on globals().copy() in accepted answer. – Victor Farazdagi Jan 22 '13 at 02:09
-
1@AgnivaDeSarker Make sure that in setting up your dictionary, you haven't called the function - i.e., that you use only the function name, with no brackets: `{'install': install}` – Hannele Apr 25 '13 at 14:31
-
I like this more, as it easy to pass parameters, and you can control the list of methods easily with dictionalry – Kostanos Feb 26 '15 at 21:35
-
I would prefer this approach to the accepted answer but I can't seem to make it work with class methods. – navjotk Feb 01 '16 at 19:16
-
@navjotk in the declaration of your dictionary: `methods = {'install': self.install}` (or `obj.install`) – Ohad Cohen Oct 06 '16 at 14:38
-
hmm, i tried something similar here but it wasn't working: https://stackoverflow.com/questions/50359442/apply-a-method-from-a-list-of-methods-to-pandas-dataframe – tired May 15 '18 at 22:05
-
If using a dictionary to store the method, the method **must** be defined before the dictionary - as in the method definition must be above the line the dictionary is on or you will get; _"NameError: name 'X' is not defined'_ – myol Nov 26 '18 at 06:51
40
Why cant we just use eval()?
def install():
print "In install"
New method
def installWithOptions(var1, var2):
print "In install with options " + var1 + " " + var2
And then you call the method as below
method_name1 = 'install()'
method_name2 = 'installWithOptions("a","b")'
eval(method_name1)
eval(method_name2)
This gives the output as
In install
In install with options a b

Renaud
- 16,073
- 6
- 81
- 79

Husain Khambaty
- 740
- 1
- 9
- 22
-
He is asking for a way to call the function with arguments. Can you detail? – Mikaël Mayer Apr 25 '13 at 13:22
-
3
-
6If you are using the above-mentioned strategy, it means that you are dynamically defining your methods/functions, in other words, they can be a lot of things, including malicious code. I suggest you [this article](http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html), and then, never using eval again. When needed, just use `json`. – lucastamoios Jan 16 '17 at 12:03
-
@lucastamoios: Not true at least in case of OP - using predefined strings as function names. – Fr0zenFyr Feb 28 '18 at 12:31
-
How do you suggest building the argument list for an arbitrary list of arguments with `installWithOptions`? Showing the hard coded example certainly doesn't tell the story here. This is all of course ignoring how horrible of a practice using eval is in the first place. I've never seen a legitimate use case for it – Cruncher Mar 20 '18 at 22:01
-
-
1@Justas Sure. In theory. But now that code is there forever, and a change that seems harmless in another file now turns out to open a giant security hole because of the use of an eval statement. You should build around as few assumption as possible. Because who knows when they'll change. – Cruncher Apr 03 '18 at 13:27
-
2`eval(method_name1)(a,b)` also works. Fair point about safety-- ok for tiny private scripts but do they stay that way? Take great care if the string is coming from a website, for example. It isn't `eval` that's the only problem here-- using `getattr` on a string from an arbitrary source is just as dangerous. – Nic Nov 15 '18 at 02:23
-
**Do not ever use `eval` on data that could possibly ever come from outside the program. It is a security hole that allows whoever creates that data to run arbitrary Python code on your computer. No, you cannot practically sandbox it.** – Karl Knechtel Aug 17 '22 at 07:53