Dynamic Loading of Python Modules

不羁的心 提交于 2019-11-28 09:31:39

I'm not sure what "it fails" means, so I'll just mention that __import__('structures.index') should, in fact, work, but it doesn't assign the module name in the current scope. To do that (and then use a class in the dynamically imported module), you'll have to use:

structures = __import__('structures.index')
structures.index.SomeClass(...)

The complete details on __import__ are available here.

Edit: (based on question edit)

To import neoform.structures.index, and return the index module, you would do the following:

structures = __import__('neoform.structures.index', 
                        fromlist=['does not in fact matter what goes here!'])

So if you have a list of package names packages, you can import their index modules and instantiate some MyClass class for each using the following code:

modules = [ __import__('neoform.%s.index' % pkg, fromlist=['a']) 
            for pkg in packages ]
objects = [ m.MyClass() for m in modules ]

To import sub-modules, you need to specify them in the fromlist arg of __import__()
Fo example, the equivalent of:

import structures.index

is:

structures = __import__('structures', fromlist=['index'])

To do this in a map is a little more tricky...

import mod1.index
import mod2.index
import mod3.index

For those imports, you would want to define a new function to get the index sub-module from each module:

def getIndexMods(mod_names):
  mod_list = map(lambda x: __import__(x, fromlist='index'))
  index_mods = [mod.index for mod in mod_list]
  return index_mods

Now, you can do this to get references to all index modules:

index_mods = getIndexMods(['mod1', 'mod2', 'mod3'])

Also, if you want to grab sub-modules that are not named 'index' then you could do this:

mod1, mod2, mod3 = map(lambda x,y: __import__(x, fromlist=y), 
  ['mod1', 'mod2', 'mod3'], ['index1', 'index2', 'index3'])

Use full scope ("neoform.structures.index") with this helper method.

def import_module(name):
    mod = __import__(name)
    components = name.split('.')
    for comp in components[1:]:
        mod = getattr(mod, comp)
    return mod

module = import_module("neoform.structures.index")
# do stuff with module

Java programmer here, but I think you need the imp module

>>> import imp
>>> fm = imp.find_module('index', ['./structures']) # for submodule
>>> mymod = imp.load_module('structures.index', *fm)
>>> mymod
<module 'structures.index' from './structures/index.pyc'>
>>> x = mymod.insideIndex()
Initialising index class...

Voila!

Why on earth would you replace

import structures.index

with

map(__import__, ["structures.index"])

The first one (a) works, (b) is dynamic and (c) is directly supported. What possible use case is there for replacing easy-to-change, plain-text source with something more complex?

In short: don't do this. It doesn't have any value.


Edit

The "I'm getting the import from a database" is a noble effort, but still not sensible. What code block depends on those imports? That whole code block -- imports and all -- is what you want to execute. That whole code block -- imports, statements and everything -- should be a plain old python module file.

Import that block of code from the file system. Use the database to identify which file, the author of the file -- anything you want to use the database for. But simply import and execute the module the simplest possible way.

Really late post here. But I was searching for this question on google. I did some trial and error. Not sure if this snippet will help but here it is. Using it for Flask site.

modules = ['frontend', 'admin']
for module in modules:
    mod = __init__('controllers.%s' % module, fromlist=[module])
    app.register_blueprint(mod.blueprint_mod)


# or
from importlib import import_module
modules = ['frontend', 'admin']
for module in modules:
    mod = import_module('controllers.%s' % module)
    app.regitster_blueprint(mod.blueprint_mod)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!