How can I import a python module function dynamically?
Asked Answered
C

7

25

Assuming my_function() is located in my_apps.views I would like to import my_function dynamically without using something like exec or eval.

Is there anyway to accomplish this. I'm looking to do something similar to:

my_function = import_func("my_apps.views.my_function")

my_function()
   ... code is executed
Careless answered 31/8, 2010 at 5:15 Comment(0)
U
36

you want

my_function = getattr(__import__('my_apps.views'), 'my_function')

If you happen to know the name of the function at compile time, you can shorten this to

my_function = __import__('my_apps.views').my_function

This will load my_apps.views and then assign its my_function attribute to the local my_function.

If you are sure that you only want one function, than this is acceptable. If you want more than one attribute, you can do:

views = __import__('my_apps.views')
my_function = getattr(views, 'my_function')
my_other_function = getattr(views, 'my_other_function')
my_attribute = getattr(views, 'my_attribute')

as it is more readable and saves you some calls to __import__. again, if you know the names, the code can be shortened as above.

You could also do this with tools from the imp module but it's more complicated.

Upperclassman answered 31/8, 2010 at 5:19 Comment(3)
There will be problems (AttributeError) with the import statements above. Import returns the first module (my_apps) unless an import list is specified. You need something like: my_function = __import__('my_apps.views', globals(), locals(), ['my_function']).my_function See python doc about importSelfassured
For me this attempts to import the function from my_apps instead of my_apps.views.Rumal
@Selfassured Actually __import__('my_apps.views', fromlist=['my_function']).my_function is enough.Southdown
T
9

Note that Python 2.7 added the importlib module, convenience wrappers for __import__() and a backport of 3.1 feature.

This module is a minor subset of what is available in the more full-featured package of the same name from Python 3.1 that provides a complete implementation of import. What is here has been provided to help ease in transitioning from 2.7 to 3.1.

importlib.import_module(name, package=None)

Import a module. The name argument specifies what module to import in absolute or relative terms (e.g. either pkg.mod or ..mod). If the name is specified in relative terms, then the package argument must be specified to the package which is to act as the anchor for resolving the package name (e.g. import_module('..mod', 'pkg.subpkg') will import pkg.mod). The specified module will be inserted into sys.modules and returned.

Toddler answered 31/8, 2010 at 5:46 Comment(1)
The subset of importlib available in Python 2.7 is also available on PyPI and is backported there to work with Python 2.3 and later.Inhibitory
H
3
def import_by_string(full_name):
    module_name, unit_name = full_name.rsplit('.', 1)
    return getattr(__import__(module_name, fromlist=['']), unit_name)


exists = import_by_string("os.path.exists")
Hengel answered 19/12, 2016 at 13:18 Comment(2)
Since version 2.4 (from 2004), Python has had the function rsplit(), it is much more efficient to do module_name, unit_name = full_name.rsplit('.', 1), than what you are doing.Wizen
Thanks. Did not think about it.Hengel
D
2

Here is my contribution to this discussion (make sure that the function names are distinct):

import importlib
modules = {
            'module1': ('func1', 'func2'),
            'module2': ('func3', 'func4', 'func5')}

imported_func = dict()
for module in modules.keys():
    imported_module = importlib.import_module(module)
    for sub_module in modules[module]:
        imported_func[sub_module] = getattr(imported_module, sub_module)

# Usage
x = imported_func['func1']()    # Insert the required arguments in the parenthesis
Dockery answered 21/9, 2023 at 11:13 Comment(0)
E
1

I just wrote this code and seems what a lot of people need, so even if later i show it

def my_import(module_name,func_names = [],cache = False):
    if module_name in globals() and cache:
        return True
    try: 
        m = __import__(module_name, globals(), locals(), func_names, -1)
        if func_names:
            for func_name in func_names:
                globals()[func_name] = getattr(m,func_name)
        else:
            globals()[module_name] = m
        return True
    except ImportError:
        return False
def my_imports(modules):
    for module in modules:
        if type(module) is tuple:
            name = module[0]
            funcs = module[1]
        else:
            name = module
            funcs = []
        if not my_import(name, funcs):
             return module
    return ''

def checkPluginsImports(plugin,modules):
    c = my_imports(modules)
    if c:
        print plugin +" has errors!: module '"+c+"' not found"

# example: file test.py with "x" function
def d():
    checkPluginsImports('demoPlugin',[('test',['x'])])

d()
x()
Ecospecies answered 23/12, 2014 at 22:11 Comment(0)
W
0

Use the standard library pkg_resources

from pkg_resources import EntryPoint
my_function  = EntryPoint.parse("my_function=my_apps.views:my_function").load(require=False)
Wellknown answered 14/7, 2022 at 12:0 Comment(0)
S
0

We have four cases separated by the fact whether the module and/or the function fixed or not:

  1. module name is a fixed string, function name is a fixed string:
    my_function = __import__('my_apps.views', fromlist=['my_function'].my_function
    
    (altough in this case it is much more simple to use from my_app.views import my_function)
  2. module name is a fixed string, function name is variable:
    function_name = ...
    .
    .
    .
    my_function = getattr(__import__('my_apps.views', fromlist=[function_name]),
                          function_name)
    
  3. module name is variable, function name is fixed string:
    module_name = ...
    .
    .
    .
    my_function = __import__(module_name, fromlist=['my_function']).my_function
    
  4. module name is variable, function name is variable:
    module_name = ...
    .
    .
    .
    function_name = ...
    .
    .
    .
    my_function = getattr(__import__(module_name, fromlist=[function_name]),
                          function_name)
    

Note: For an empty list (that's the default value) as __import__ keyword argument fromlist not the module, but the package root is returned. For all non-empty lists the actual module returned.

Sources and further information:

Southdown answered 8/9, 2022 at 12:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.