Dynamically import a method in a file, from a string
Solution 1
From Python 2.7 you can use the importlib.import_module() function. You can import a module and access an object defined within it with the following code:
from importlib import import_module
p, m = name.rsplit('.', 1)
mod = import_module(p)
met = getattr(mod, m)
met()
Solution 2
You don't need to import the individual modules. It is enough to import the module you want to import a name from and provide the fromlist
argument:
def import_from(module, name):
module = __import__(module, fromlist=[name])
return getattr(module, name)
For your example abc.def.ghi.jkl.myfile.mymethod
, call this function as
import_from("abc.def.ghi.jkl.myfile", "mymethod")
(Note that module-level functions are called functions in Python, not methods.)
For such a simple task, there is no advantage in using the importlib
module.
Solution 3
For Python < 2.7 the builtin method __ import__ can be used:
__import__('abc.def.ghi.jkl.myfile.mymethod', fromlist=[''])
For Python >= 2.7 or 3.1 the convenient method importlib.import_module has been added. Just import your module like this:
importlib.import_module('abc.def.ghi.jkl.myfile.mymethod')
Update: Updated version according to comments (I must admit I didn't read the string to be imported till the end and I missed the fact that a method of a module should be imported and not a module itself):
Python < 2.7 :
mymethod = getattr(__import__("abc.def.ghi.jkl.myfile", fromlist=["mymethod"]))
Python >= 2.7:
mymethod = getattr(importlib.import_module("abc.def.ghi.jkl.myfile"), "mymethod")
Solution 4
from importlib import import_module
name = "file.py".strip('.py')
# if Path like : "path/python/file.py"
# use name.replaces("/",".")
imp = import_module(name)
# get Class From File.py
model = getattr(imp, "classNameImportFromFile")
NClass = model() # Class From file
Solution 5
It's unclear what you are trying to do to your local namespace. I assume you want just my_method
as a local, typing output = my_method()
?
# This is equivalent to "from a.b.myfile import my_method"
the_module = importlib.import_module("a.b.myfile")
same_module = __import__("a.b.myfile")
# import_module() and __input__() only return modules
my_method = getattr(the_module, "my_method")
# or, more concisely,
my_method = getattr(__import__("a.b.myfile"), "my_method")
output = my_method()
While you only add my_method
to the local namespace, you do load the chain of modules. You can look at changes by watching the keys of sys.modules
before and after the import. I hope this is clearer and more accurate than your other answers.
For completeness, this is how you add the whole chain.
# This is equivalent to "import a.b.myfile"
a = __import__("a.b.myfile")
also_a = importlib.import_module("a.b.myfile")
output = a.b.myfile.my_method()
# This is equivalent to "from a.b import myfile"
myfile = __import__("a.b.myfile", fromlist="a.b")
also_myfile = importlib.import_module("a.b.myfile", "a.b")
output = myfile.my_method()
And, finally, if you are using __import__()
and have modified you search path after the program started, you may need to use __import__(normal args, globals=globals(), locals=locals())
. The why is a complex discussion.
Related videos on Youtube
lprsd
I am a curious learner! You should follow me on twitter as @lprsd_
Updated on July 08, 2022Comments
-
lprsd almost 2 years
I have a string, say:
abc.def.ghi.jkl.myfile.mymethod
. How do I dynamically importmymethod
?Here is how I went about it:
def get_method_from_file(full_path): if len(full_path) == 1: return map(__import__,[full_path[0]])[0] return getattr(get_method_from_file(full_path[:-1]),full_path[-1]) if __name__=='__main__': print get_method_from_file('abc.def.ghi.jkl.myfile.mymethod'.split('.'))
I am wondering if the importing individual modules is required at all.
Edit: I am using Python version 2.6.5.
-
lprsd over 12 yearsI use 2.6.5. Can I do a
from __future__
thing? -
ThiefMaster over 12 yearsNo,
__future__
is for language features, not new stdlib modules. -
Kris Hardy over 12 yearsNeither of these solutions will not work because the first parameter must be a module name in both
__import__()
andimportlib.import_module()
. -
frm over 12 yearsimportlib.import_module('abc.def.ghi.jkl.myfile.mymethod') will not work because you have to specify "what module to import in absolute or relative terms" and not the "qualified" name of the method.
-
lprsd over 12 yearsThis does not work, obviously, as the first parameter to import should be a module, not a string.
-
Sven Marnach over 12 yearsWhy should anybdoy do this? This requires the caller to join module name and attribute name with a colon, and the function needs to split again at the colon. Why not simply use two parameters in the first place?
-
Kris Hardy over 12 yearsOften, a situation where this will come up is if you wire callbacks from a framework to your application using configuration files (.yaml, .ini, etc.). Then, you can specify which function the framework should call, etc., with a single string in your configuration file.
-
Sven Marnach over 12 yearsWell, yeah, you might want to choose this as a configuration file syntax. But how is this related to the OP's question? (And even if I had chosen this as my config file syntax, I'd prefer to have it parsed by my config file parser, not by random API functions.)
-
Charles Merriam about 11 yearsUse the buit-in
__import__
as in the examples above. It works back to 2.5 and, without keywords, before that. -
Fydo over 10 yearsimport_from() pointed me in the right direction.
myClass = getattr(__import__("module.to.import", fromlist=["myClassName"]), "myClassName")
. Thanks for the help! -
sleepycal almost 10 yearsYour first example of
the_module
andsame_module
is wrong and produce different results. Downvoting. -
twasbrillig about 9 yearsThe
__import__
approach does work. But try runninghelp(__import__)
. It says "Because this function is meant for use by the Python interpreter and not for general use it is better to useimportlib.import_module()
to programmatically import a module." -
Sven Marnach about 9 years@twasbrillig: When I answered this question, Python 2.5 and 2.6 were still in widespread use. Today, it's certainly best to use
importlib
instead. -
twasbrillig about 9 yearsCool, thanks. Might be a good idea to update the answer to reflect this.
-
BoltzmannBrain over 8 yearsWorth noting the Python docs recommend using
importlib.import_module()
over__import__()
: docs.python.org/2/library/functions.html#__import__ -- for 2.7+. -
Cecil Curry over 7 years
import_module
+rsplit
= The One True Way. -
Yet Another User almost 6 yearsPlease include the summary/code from the given link. Link-only answers are not great because they are prone to link rot.
-
jxmorris12 about 4 yearsThanks for the answer, just one small problem: I don't think
.strip()
behaves correctly in the case you stated. Specifically, if the file starts with "py", those characters will be removed as well. For example,"pyfile.py".strip(".py")
produces"file"
, where it'd be preferred that it produce"pyfile"
in this case.name.replace(".py","")
works just fine, though. -
dephinera over 3 yearsUsing the magic method is discouraged. Use importlib instead.
-
Aymen Alsaadi over 3 yearsCan you elaborate on why it is discouraging? @dephinera
-
dephinera over 3 yearsWell because magic methods are intended to be called by the interpreter, not explicitly by our code. By calling them explicitly, we rely that their signature will never change, however it might change in a future language versions.
-
Aymen Alsaadi over 3 years@dephinera, I did not see anything like that before. Can you reference a link. I googled it and could not find anything.