Calling a function of a module by using its name (a string)
Asked Answered
B

18

2430

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()
Bree answered 6/8, 2008 at 3:36 Comment(2)
Using eval would probably bring up some security concerns!Tiemannite
FYI: the language feature of accessing fields, classes and methods by dynamic names is called reflection. Might make future searches easier.Stria
S
2923

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.

Strobotron answered 6/8, 2008 at 3:57 Comment(17)
hasattr or getattr can be used to determine if a function is defined. I had a database mapping (eventType and handling functionName) and I wanted to make sure I never "forgot" to define an event handler in my pythonForde
This works if you already know the module name. However, if you want the user to provide the module name as a string, this won't work.Gora
If you need to avoid a NoneType is not callable exception, you could also employ the three-argument form of getattr: getattr(foo, 'bar', lambda: None). I apologize for the formatting; the stackexchange android app is apparently terrible.Scheffler
See also the answer provided by @sastanin if you only care for example about your local/current module's functions.Naumachia
This does not work with functions that use a decorator. getattr returns the outer functionCavanaugh
Note: cool +1, this made me understand once more that in Python everything is an object. Consequently, it works also with variables, you can access a module's variables as any other object's variables.Canica
If you have deep structures, the following syntax might be useful: from functools import reduce reduce(getattr, "a.b.c.d.e.f.g".split('.'), deepStructure)Ecdysiast
This is a very helpful answer, buy I couldn't work it out when the module foo is the current module itself. Does anybody know how to do that?Caceres
@Caceres Yes, if you're in the foo module you can use globals() to do this: methodToCall = globals()['bar']Mordacious
You CAN do this, but SHOULD you? How will you find all instances of your function call when your code base gets large? There's nothing to grep for, and no IDE is going to find that reference. That makes this sort of dynamic call really troublesome. Isn't it nicer to your colleagues to be explicit, anyway? Less code doesn't doesn't always mean more readable.Zamir
@Zamir since we do not know the use case, only the question, all I can say reliably is that there are many use cases in which your point applies, and some which they do not. It is common and reasonable to do things like this in rules engines, DSLs, in-app scripting, etc., in which the code you are writing exists to run other code. There are probably numerous other "good" times to do this that I'm not thinking of right now. So, should we do this? The answer, as with most language features in most languages, is "it depends."Strobotron
@PatrickJohnmeyer I never exclude patterns/paradigms entirely... This is why I asked a question instead of making a blanket statement. There are a lot of negative repercussions for using this pattern overzealously... which (at least in my experience) is common.Zamir
In case, if the module itself is a string and one has to convert from str to class in this case "foo" is a string but it has to be called, then checkout this link blender.stackexchange.com/questions/36781/… PS: I know it's doesn't belong in the context of the asked question, I thought someone might benefit from this comment.Openhanded
can we get this foo also from string?Porkpie
@Porkpie you can, using something like 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-stringStrobotron
If we want the method with parameter in that case how to doShiff
What should I do to detect local function within the module itself?Reliant
T
772
  • Using locals(), which returns a dictionary with the current local symbol table:

    locals()["myfunction"]()
    
  • Using globals(), which returns a dictionary with the global symbol table:

    globals()["myfunction"]()
    
Traci answered 7/5, 2009 at 12:45 Comment(4)
This method with globals/locals is good if the method you need to call is defined in the same module you are calling from.Gurango
@Gurango is there any other way to get an object by string out of the root namespace?Tutor
@NickT I am only aware of these methods, I don't think there are any others that fill same function as these, at least I can't think of a reason why there should be more.Gurango
I've got a reason for you (actually what led me here): Module A has a function F that needs to call a function by name. Module B imports Module A, and invokes function F with a request to call Function G, which is defined in Module B. This call fails because, apparently, function F only runs with the globals that are defined in Module F - so globals()['G'] = None.Expatriate
K
478

Based on Patrick's solution, to get the module dynamically as well, import it using:

module = __import__('foo')
func = getattr(module, 'bar')
func()
Kriemhild answered 7/8, 2008 at 11:35 Comment(7)
I do not understand that last comment. __import__ has its own right and the next sentence in the mentioned docs says: "Direct use of __import__() is rare, except in cases where you want to import a module whose name is only known at runtime". So: +1 for the given answer.Beebe
Use 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
@Traveller As long as you're ok with only support 2.7 and up.Kare
@Xiong Chaimiov, importlib.import_module is supported in 3.6 . See docs.python.org/3.6/library/…Margeret
@Margeret Yes, 3.6 is part of "2.7 and up", both in strict versioning semantics and in release dates (it came about six years later). It also didn't exist for three years after my comment. ;) In the 3.x branch, the module has been around since 3.1. 2.7 and 3.1 are now pretty ancient; you'll still find servers hanging around that only support 2.6, but it's probably worth having importlib be the standard advice nowadays.Kare
For module paths using dot format, e.g. 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
@ConnerM. Yep and definitely worth noting! I think it should be added to the answer. More officially from the relevant docs, "The most important difference between these two functions is that import_module() returns the specified package or module (e.g. pkg.mod), while __import__() returns the top-level package or module (e.g. pkg)."Arteriovenous
K
165

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')
Katykatya answered 19/8, 2012 at 9:40 Comment(1)
What if you call this function inside a class function?Burdick
R
161

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()
Ronnyronsard answered 16/10, 2013 at 0:24 Comment(2)
This helped me. Its a lightweight version of __import__ function.Bluestocking
I think this was the best answer.Kindergarten
K
89

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

Kalikow answered 24/10, 2016 at 13:20 Comment(0)
E
72

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")()
Empirical answered 9/4, 2014 at 10:17 Comment(2)
this could be improved by recursively scanning the directory tree and auto-mounting usb drivesGomorrah
This is definitely the answer I wanted. Perfect.Mungo
U
47

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)
Urinate answered 7/12, 2016 at 18:29 Comment(4)
This would be risky. string can have anything and eval would end up eval-ling it without any consideration.Lubricous
Sure, you must be mindful of the context you are using it in, whether this will be appropriate or not, given those risks.Urinate
A function should not be responsible for validating it's parameters - that's the job of a different function. Saying that it's risky to use eval with a string is saying that use of every function is risky.Detumescence
You should never use eval unless strictly necessary. getattr(__module__, method_name) is a much better choice in this context.Varietal
W
43

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)
Wyckoff answered 14/2, 2012 at 5:55 Comment(2)
Just a bit more generic is handler = getattr(sys.modules[__name__], myFnName)Gonion
how does it work if function is a class function?Burdick
B
21

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

Brashy answered 26/3, 2019 at 18:15 Comment(3)
Great answer, thank you :) I was trying the same approach, but failed not knowing that I have to include "self" in the actual function call again. Do you have an explanation as to why this is necessary?Standridge
My best guess: obj.method in Python actually calls method(self, ...), in case of getattr this synthetic sugar could not be applied by Python interpreter.Brashy
best answer. the point is using class name instead of "self" in getattr command.i was trying to use like getattr(self, key)() and it was giving error like int is not callable but when i changed it to " getattr(HomeScreen, key)(self)" it is working now. "HomeScreen" is class name by the way..thanks...Slily
E
18

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

Efficient answered 28/12, 2012 at 16:56 Comment(4)
In what aspect is this better than getattr() ?Deviate
Exactly what i wanted. Works like a charm! Perfect!! self.__getattribute__('title') is equal to self.titleWilscam
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() insteadWilscam
Can people who don't know python please stop upvoting this junk? Use getattr instead.Jeffjeffcoat
W
17

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')
Whimsy answered 16/7, 2020 at 15:20 Comment(0)
P
17

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]
Parquet answered 7/7, 2021 at 9:30 Comment(1)
This is a duplicate of this answer, and is also not the best practice for the same reasons: just use getattr(obj, attr) instead.Bluma
T
12

Nobody mentioned operator.attrgetter yet:

>>> from operator import attrgetter
>>> l = [1, 2, 3]
>>> attrgetter('reverse')(l)()
>>> l
[3, 2, 1]
>>> 
Tarver answered 20/9, 2021 at 6:13 Comment(0)
T
8

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."
Treytri answered 1/7, 2020 at 8:9 Comment(0)
S
3

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.

Stoss answered 15/6, 2021 at 8:14 Comment(3)
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
@Bluma yes, you're right! and this also makes the variable visable to the following codes. thanks!Stoss
@Bluma but exec could let me define a series of variables with different names, like exec(f"x{i} = {i}"), which eval cannot do.Stoss
J
1

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
Jestinejesting answered 23/3 at 19:39 Comment(0)
H
-16

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\")")
Hydrate answered 28/8, 2019 at 16:46 Comment(3)
This is not what op asks.Fidget
this code snippet contains the worst 2 security flaws, nested. Some kind of a record.Dasilva
This must have been posted at the wrong question. Please, just delete it.Gorman

© 2022 - 2024 — McMap. All rights reserved.