Welcome, guest | Sign In | My Account | Store | Cart

This recipe lets you import any file as a module. It's not required that the file is in the Python search path. This is done without having to modify sys.path (even temporarily)

Python, 8 lines
1
2
3
4
5
6
7
8
import imp, os.path

def import_(filename):
    (path, name) = os.path.split(filename)
    (name, ext) = os.path.splitext(name)

    (file, filename, data) = imp.find_module(name, [path])
    return imp.load_module(name, file, filename, data)

Of course the extension of the filename will be ignore, e.g. m = import_("/usr/local/lib/python2.2/mimetypes.foo") will work, and will import mimetypes.pyc and not the non-existing mimetypes.foo

2 comments

Michael Palmer 18 years, 6 months ago  # | flag

Potential name conflicts in sys.modules. imp.load_modules will also put the imported module in sys.modules, using as a key the name determined in import_ (see below). If some other module was already there, it will be replaced. So to some extent you are loosing control of your program's state.

Customized module import is not easy to do in clean way.

import imp, os.path, sys

def import_(filename):
    path, name = os.path.split(filename)
    name, ext = os.path.splitext(name)

    print 'Before: %s in sys.modules ==' % name, name in sys.modules
    file, filename, data = imp.find_module(name, [path])
    mod = imp.load_module(name, file, filename, data)
    print 'After: %s in sys.modules ==' % name, name in sys.modules
    return mod

if __name__ == '__main__':
    rePath = imp.find_module('re')[1]
    import_ (rePath)
Phil Groce 18 years, 2 months ago  # | flag

Managing sys.modules with load_module. The important thing is to manage the names of your modules in a way that avoids namespace conflicts and always (re)loads a module in the same place in sys.modules. This recipe might work better like this:

import imp, os.path, sys

def import_(filename, prefix):
    path, name = os.path.split(filename)
    name, ext = os.path.splitext(name)

    modname = "%s_%s" % (prefix, name)

    print 'Before: %s in sys.modules ==' % modname, modname in sys.modules
    print 'Before: %s in sys.modules ==' % name, name in sys.modules
    file, filename, data = imp.find_module(name, [path])
    mod = imp.load_module(name, file, filename, data)
    print 'After: %s in sys.modules ==' % modname, modname in sys.modules
    print 'After: %s in sys.modules ==' % name, name in sys.modules
    return mod

if __name__ == '__main__':
    rePath = imp.find_module('re')[1]
    import_ (rePath, "example")

This produces the following output:

Before: example_re in sys.modules == False
Before: re in sys.modules == False
After: example_re in sys.modules == True
After: re in sys.modules == False

It's still tricky -- nothing prevents someone from importing a different 'example_re,' and overwriting your entry in sys.modules, for instance. If you're not prepared to deal with this sort of thing, though, you shouldn't muck about with runtime module loading.