|
|||||||
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 |
|||||||
Так же в этом разделе:
|
|||||||
|
|||||||
|