user967569
user967569

Reputation: 23

Python: import modules dynamically in different namespace

import v_framework as framework
framework.loadModules(["Maintenance"])
framework.Maintenance.showPage()

In framework I have:

def loadModules(aModules):
    d_utility = {"Maintenance":"COOl_M_PAGE"}
    for module in a_aModules:
        exec("import " + d_utility[module] + " as " + module)

When loadModules is executed, it imports the modules in the v_framework namespace. Since I am importing v_framework as framework, I think I should be able to use the imported module using framework.Maintenance. But it does not work that way. Is there a way to do way to do what I'm trying to do? Alternatively, is there any way to import modules in a namespace other than the one where exec is executed?

Upvotes: 2

Views: 3475

Answers (2)

Ismail Badawi
Ismail Badawi

Reputation: 37177

When you import inside a function, the module is imported/executed as normal, but the name you import under is local to the function, just like any other variable assigned inside a function.

>>> def test_import():
...    import os
...    print os
...
>>> test_import()
<module 'os' from '/usr/lib/python2.7/os.pyc'>
>>> os
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined

os has been imported though, and you can still access it through sys.modules:

>>> import sys
>>> sys.modules['os']
<module 'os' from '/usr/lib/python2.7/os.pyc'>
>>> os = sys.modules['os']
>>> os
<module 'os' from '/usr/lib/python2.7/os.pyc'>

A quick and dirty way to do what you want would be something like this; exec takes an optional mapping to be used as the local and global variables. So you could do

def loadModules(aModules):
    d_utility = {"Maintenance":"COOl_M_PAGE"}
    for module in aModules:
        exec ('import %s as %s' % (d_utility[module], module)) in globals()

Though this is ugly and probably has security implications or something. As jadkik94 mentions, there are libraries that provide cleaner ways to deal with this.

Upvotes: 1

jadkik94
jadkik94

Reputation: 7068

There are libraries for importing modules dynamically. You could use importlib (and another one that might be useful is pkgutil). Now, for your case, I guess this would do the job:

import importlib
mods = {}
def loadModules(aModule):
    global mods
    mods[module] = importlib.import_module(d_utility[module])
    # or maybe globals()[module] = ... would work also (exactly as you expect it to

UPDATE: exec modifies the function's local namespace, not the global one (I think).

Hope it helps. :)

Upvotes: 1

Related Questions