MyTetra Share
Делитесь знаниями!
Calling a function of a module by using its name (a string)
Время создания: 17.07.2018 10:16
Текстовые метки: python call function string name
Раздел: Python
Запись: Velonski/mytetra-database/master/base/1531804602uasj72dac5/text.html на raw.githubusercontent.com

What is the best way to go about calling a function given a string with the function's name in a Python program. For example, let's say that I have a module foo, and I have a string whose contents are "bar". What is the best way to go about calling foo.bar()?


I need to get the return value of the function, which is why I don't just use eval. I figured out how to do it by using eval to define a temp function that returns the result of that function call, but I'm hoping that there is a more elegant way to do this.


python

shareimprove this question

edited Dec 31 '17 at 3:23


Claus Wilke

6,65332442

asked Aug 6 '08 at 3:36


ricree

10.6k132927

add a comment

10 Answers

active oldest votes

up vote

1429

down vote

accepted

Assuming module foo with method bar:


import foo

method_to_call = getattr(foo, 'bar')

result = method_to_call()

As far as that goes, lines 2 and 3 can be compressed to:


result = getattr(foo, 'bar')()

if that makes more sense for your use case. You can use getattr in this fashion on class instance bound methods, module-level methods, class methods... the list goes on.


shareimprove this answer

edited Feb 22 '17 at 18:10


Ben Hoyt

5,76333972

answered Aug 6 '08 at 3:57


Patrick Johnmeyer

16.4k11823

5

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 python – Shaun Jun 3 '14 at 13:20

4

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. – Blairg23 Jun 21 '14 at 7:39

5

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. – geekofalltrades Aug 16 '14 at 18:01

3

See also the answer provided by @sastanin if you only care for example about your local/current module's functions. – NuSkooler Jun 19 '15 at 22:19

1

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. – tuned Aug 29 '15 at 17:54

show 10 more comments

up vote

398

down vote

locals()["myfunction"]()

or


globals()["myfunction"]()

locals returns a dictionary with a current local symbol table. globals returns a dictionary with global symbol table.


shareimprove this answer

answered May 7 '09 at 12:45


sastanin

26k879122

26

This method with globals/locals is good if the method you need to call is defined in the same module you are calling from. – Joelmob Oct 9 '14 at 21:36

@Joelmob is there any other way to get an object by string out of the root namespace? – Nick T Jan 26 '15 at 20:51

@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. – Joelmob Jan 27 '15 at 12:34

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. – David Stein Jan 30 '17 at 15:18

add a comment

up vote

239

down vote

Patrick's solution is probably the cleanest. If you need to dynamically pick up the module as well, you can import it like:


module = __import__('foo')

func = getattr(module, 'bar')

func()

shareimprove this answer

edited Feb 22 '17 at 18:08


Ben Hoyt

5,76333972

answered Aug 7 '08 at 11:35


HS.

10.2k73246

80

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. – hoffmaje May 5 '12 at 9:33

34

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__ – glarrain Aug 5 '13 at 22:07

7

@glarrain As long as you're ok with only support 2.7 and up. – Xiong Chiamiov Sep 14 '13 at 16:54

@Xiong Chaimiov, importlib.import_module is supported in 3.6 . See docs.python.org/3.6/library/… – cowlinator Oct 5 '17 at 19:28

5

@cowlinator 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. – Xiong Chiamiov Oct 5 '17 at 23:55

add a comment

up vote

81

down vote

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')

shareimprove this answer

edited Sep 22 '14 at 21:49


tbc0

751814

answered Aug 19 '12 at 9:40


Sourcegeek

81962

add a comment

up vote

65

down vote

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()

shareimprove this answer

answered Oct 16 '13 at 0:24


ferrouswheel

2,0131621

This helped me. Its a lightweight version of __import__ function. – Pankaj Bhambhani Dec 16 '15 at 13:19

Neat solution mate! – Nebulosar Apr 10 at 12:52

add a comment

up vote

30

down vote

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")()

shareimprove this answer

answered Apr 9 '14 at 10:17


00500005

1,67611732

add a comment

up vote

28

down vote

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


shareimprove this answer

answered Oct 24 '16 at 13:20

user3946687

add a comment

up vote

18

down vote

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)

shareimprove this answer

answered Feb 14 '12 at 5:55


trubliphone

1,27422134

Just a bit more generic is handler = getattr(sys.modules[__name__], myFnName) – lony Oct 6 '17 at 12:33

add a comment

up vote

15

down vote

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)

shareimprove this answer

edited Dec 8 '16 at 18:09

answered Dec 7 '16 at 18:29


tvt173

690714

This would be risky. string can have anything and eval would end up eval-ling it without any consideration. – iankit Dec 30 '16 at 18:13

1

Sure, you must be mindful of the context you are using it in, whether this will be appropriate or not, given those risks. – tvt173 Jan 6 '17 at 18:48

add a comment

up vote

13

down vote

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


shareimprove this answer

answered Dec 28 '12 at 16:56


Natdrip

435415

7

In what aspect is this better than getattr() ? – V13 Jul 29 '16 at 12:26

Так же в этом разделе:
 
MyTetra Share v.0.59
Яндекс индекс цитирования