How do I call a function, using a string with the function's name? For example:
import foo
func_name = "bar"
call(foo, func_name) # calls foo.bar()
How do I call a function, using a string with the function's name? For example:
import foo
func_name = "bar"
call(foo, func_name) # calls foo.bar()
Given a module foo
with method bar
:
import foo
bar = getattr(foo, 'bar')
result = bar()
getattr
can similarly be used on class instance bound methods, module-level methods, class methods... the list goes on.
foo
module you can use globals()
to do this: methodToCall = globals()['bar']
–
Mordacious m = __import__('foo')
, where m
is now the name used for module "foo". You would then do method_to_call = getattr(m, 'bar')
. Calling __import__
directly is rarely the right answer, but it is possible. https://mcmap.net/q/40512/-calling-a-function-of-a-module-by-using-its-name-a-string –
Strobotron Based on Patrick's solution, to get the module dynamically as well, import it using:
module = __import__('foo')
func = getattr(module, 'bar')
func()
importlib.import_module
. The official docs say about __import__
: "This is an advanced function that is not needed in everyday Python programming, unlike importlib.import_module()." docs.python.org/2/library/functions.html#__import__ –
Traveller importlib.import_module
is supported in 3.6 . See docs.python.org/3.6/library/… –
Margeret foo.bar.module
, __input__
only imports the base module foo
, whereas importlib.import_module
returns foo.bar.module
. Using 'foo/bar/module,
__import__` returns expected module. –
Shell Just a simple contribution. If the class that we need to instance is in the same file, we can use something like this:
# Get class from globals and create an instance
m = globals()['our_class']()
# Get the function (from the instance) that we need to call
func = getattr(m, 'function_name')
# Call it
func()
For example:
class A:
def __init__(self):
pass
def sampleFunc(self, arg):
print('you called sampleFunc({})'.format(arg))
m = globals()['A']()
func = getattr(m, 'sampleFunc')
func('sample arg')
# Sample, all on one line
getattr(globals()['A'](), 'sampleFunc')('sample arg')
And, if not a class:
def sampleFunc(arg):
print('you called sampleFunc({})'.format(arg))
globals()['sampleFunc']('sample arg')
Given a string, with a complete python path to a function, this is how I went about getting the result of said function:
import importlib
function_string = 'mypackage.mymodule.myfunc'
mod_name, func_name = function_string.rsplit('.',1)
mod = importlib.import_module(mod_name)
func = getattr(mod, func_name)
result = func()
__import__
function. –
Bluestocking The best answer according to the Python programming FAQ would be:
functions = {'myfoo': foo.bar}
mystring = 'myfoo'
if mystring in functions:
functions[mystring]()
The primary advantage of this technique is that the strings do not need to match the names of the functions. This is also the primary technique used to emulate a case construct
The answer (I hope) no one ever wanted
Eval like behavior
getattr(locals().get("foo") or globals().get("foo"), "bar")()
Why not add auto-importing
getattr(
locals().get("foo") or
globals().get("foo") or
__import__("foo"),
"bar")()
In case we have extra dictionaries we want to check
getattr(next((x for x in (f("foo") for f in
[locals().get, globals().get,
self.__dict__.get, __import__])
if x)),
"bar")()
We need to go deeper
getattr(next((x for x in (f("foo") for f in
([locals().get, globals().get, self.__dict__.get] +
[d.get for d in (list(dd.values()) for dd in
[locals(),globals(),self.__dict__]
if isinstance(dd,dict))
if isinstance(d,dict)] +
[__import__]))
if x)),
"bar")()
Try this. While this still uses eval, it only uses it to summon the function from the current context. Then, you have the real function to use as you wish.
The main benefit for me from this is that you will get any eval-related errors at the point of summoning the function. Then you will get only the function-related errors when you call.
def say_hello(name):
print 'Hello {}!'.format(name)
# get the function by name
method_name = 'say_hello'
method = eval(method_name)
# call it like a regular function later
args = ['friend']
kwargs = {}
method(*args, **kwargs)
eval
unless strictly necessary. getattr(__module__, method_name)
is a much better choice in this context. –
Varietal For what it's worth, if you needed to pass the function (or class) name and app name as a string, then you could do this:
myFnName = "MyFn"
myAppName = "MyApp"
app = sys.modules[myAppName]
fn = getattr(app,myFnName)
handler = getattr(sys.modules[__name__], myFnName)
–
Gonion As this question How to dynamically call methods within a class using method-name assignment to a variable [duplicate] marked as a duplicate as this one, I am posting a related answer here:
The scenario is, a method in a class want to call another method on the same class dynamically, I have added some details to original example which offers some wider scenario and clarity:
class MyClass:
def __init__(self, i):
self.i = i
def get(self):
func = getattr(MyClass, 'function{}'.format(self.i))
func(self, 12) # This one will work
# self.func(12) # But this does NOT work.
def function1(self, p1):
print('function1: {}'.format(p1))
# do other stuff
def function2(self, p1):
print('function2: {}'.format(p1))
# do other stuff
if __name__ == "__main__":
class1 = MyClass(1)
class1.get()
class2 = MyClass(2)
class2.get()
Output (Python 3.7.x)
function1: 12
function2: 12
none of what was suggested helped me. I did discover this though.
<object>.__getattribute__(<string name>)(<params>)
I am using python 2.66
Hope this helps
self.__getattribute__('title')
is equal to self.title
–
Wilscam self.__getattribute__('title')
doesn't work in any cases(don't know why) afterall, but func = getattr(self, 'title'); func();
does. So, maybe is better to use getattr()
instead –
Wilscam getattr
instead. –
Jeffjeffcoat Although getattr() is elegant (and about 7x faster) method, you can get return value from the function (local, class method, module) with eval as elegant as x = eval('foo.bar')()
. And when you implement some error handling then quite securely (the same principle can be used for getattr). Example with module import and class:
# import module, call module function, pass parameters and print retured value with eval():
import random
bar = 'random.randint'
randint = eval(bar)(0,100)
print(randint) # will print random int from <0;100)
# also class method returning (or not) value(s) can be used with eval:
class Say:
def say(something='nothing'):
return something
bar = 'Say.say'
print(eval(bar)('nice to meet you too')) # will print 'nice to meet you'
When module or class does not exist (typo or anything better) then NameError is raised. When function does not exist, then AttributeError is raised. This can be used to handle errors:
# try/except block can be used to catch both errors
try:
eval('Say.talk')() # raises AttributeError because function does not exist
eval('Says.say')() # raises NameError because the class does not exist
# or the same with getattr:
getattr(Say, 'talk')() # raises AttributeError
getattr(Says, 'say')() # raises NameError
except AttributeError:
# do domething or just...
print('Function does not exist')
except NameError:
# do domething or just...
print('Module does not exist')
In python3, you can use the __getattribute__
method. See following example with a list method name string:
func_name = 'reverse'
l = [1, 2, 3, 4]
print(l)
>> [1, 2, 3, 4]
l.__getattribute__(func_name)()
print(l)
>> [4, 3, 2, 1]
getattr(obj, attr)
instead. –
Bluma Nobody mentioned operator.attrgetter
yet:
>>> from operator import attrgetter
>>> l = [1, 2, 3]
>>> attrgetter('reverse')(l)()
>>> l
[3, 2, 1]
>>>
getattr
calls method by name from an object.
But this object should be parent of calling class.
The parent class can be got by super(self.__class__, self)
class Base:
def call_base(func):
"""This does not work"""
def new_func(self, *args, **kwargs):
name = func.__name__
getattr(super(self.__class__, self), name)(*args, **kwargs)
return new_func
def f(self, *args):
print(f"BASE method invoked.")
def g(self, *args):
print(f"BASE method invoked.")
class Inherit(Base):
@Base.call_base
def f(self, *args):
"""function body will be ignored by the decorator."""
pass
@Base.call_base
def g(self, *args):
"""function body will be ignored by the decorator."""
pass
Inherit().f() # The goal is to print "BASE method invoked."
i'm facing the similar problem before, which is to convert a string to a function. but i can't use eval()
or ast.literal_eval()
, because i don't want to execute this code immediately.
e.g. i have a string "foo.bar"
, and i want to assign it to x
as a function name instead of a string, which means i can call the function by x()
ON DEMAND.
here's my code:
str_to_convert = "foo.bar"
exec(f"x = {str_to_convert}")
x()
as for your question, you only need to add your module name foo
and .
before {}
as follows:
str_to_convert = "bar"
exec(f"x = foo.{str_to_convert}")
x()
WARNING!!! either eval()
or exec()
is a dangerous method, you should confirm the safety.
WARNING!!! either eval()
or exec()
is a dangerous method, you should confirm the safety.
WARNING!!! either eval()
or exec()
is a dangerous method, you should confirm the safety.
eval()
can be used here instead of exec()
, and would probably make the code marginally more readable: just use x = eval(str_to_convert)
instead for the same result. –
Bluma Verified and tested:
# demo.py
import sys
def f1():
print("Function 1 called")
def f2():
print("Function 2 called")
def f3():
print("Function 3 called")
def f4():
print("Function 4 called")
functions = {
"f1": __name__,
"f2": __name__,
"f3": __name__,
"f4": __name__
}
function_name = input("Enter the name of the function you want to call: ")
try:
func = getattr(sys.modules[functions[function_name]], function_name)
except Exception as e:
print(f"Error: {e}")
else:
func()
Test:
% python3 demo.py
Enter the name of the function you want to call: f1
Function 1 called
This is a simple answer, this will allow you to clear the screen for example. There are two examples below, with eval and exec, that will print 0 at the top after cleaning (if you're using Windows, change clear
to cls
, Linux and Mac users leave as is for example) or just execute it, respectively.
eval("os.system(\"clear\")")
exec("os.system(\"clear\")")
© 2022 - 2024 — McMap. All rights reserved.