4

I'm searching for a way to import modules from a location on the local filesystem without the requirement of appending the parent-directory to sys.path. Here's example-code showing the demanded interface:

imp = Importer()
imp.add_path(r'C:\pylibs')
foolib = imp.import_('foolib')
print foolib
# <module 'foolib' from 'C:\pylibs\foolib.py'>

I can think of an implementation like this, but I was wondering if it is possible without the workaround of exchanging the sys.path variable temporaribly.

import sys

class Importer(object):

    def __init__(self):
        super(Importer, self).__init__()
        self.path = []

    def add_path(self, path):
        self.path.append(path)

    def import_(self, name):
        old_path = sys.path
        sys.path = self.path

        try:
            return __import__(name, {}, {})
        finally:
            sys.path = old_path
3
  • If you want to add an answer, then do so in an answer rather than a question. I reverted the question to its original form. Commented Jan 6, 2013 at 14:16
  • @DavidHeffernan: The correct answer is was the one from C0deH4cker. Where else should I put the final code?! Imho it does not make much sense to put it into a new answer. Commented Jan 6, 2013 at 15:17
  • 1
    Yes it does make perfect sense to put it in a new answer. It was a nice piece of code that could be useful to future visitors. You have accepted the right answer. Adding another answer to provide more help is fine and encouraged. Commented Jan 6, 2013 at 15:21

3 Answers 3

3

Try looking into the imp module.

Specifically, the functions

imp.find_module(name[, path])

and

imp.load_module(name, file, pathname, description)

look useful.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much. I've edited the question to include the new code.
1

Final Code

Thanks to C0deH4cker.

import sys
import imp

class Importer(object):
    r"""
    Use this class to enable importing modules from specific
    directories independent from `sys.path`.
    """

    def __init__(self):
        super(Importer, self).__init__()
        self.path = []

    def add(self, *paths):
        r"""
        Add the passed strings to the search-path for importing
        modules. Raises TypeError if non-string object was passed.
        Passed paths are automatically expanded.
        """

        new_paths = []
        for path in paths:
            if not isinstance(path, basestring):
                raise TypeError('passed argument must be string.')
            path = os.path.expanduser(path)
            new_paths.append(path)

        self.path.extend(new_paths)

    def import_(self, name, load_globally=False):
        r"""
        Import the module with the given name from the directories
        added to the Importer. The loaded module will not be inserted
        into `sys.modules` unless `load_globally` is True.
        """

        prev_module = None
        if name in sys.modules and not load_globally:
            prev_module = sys.modules[name]
            del sys.modules[name]

        data = imp.find_module(name, self.path)
        try:
            return imp.load_module(name, *data)
        except:
            data[0].close()
            raise
        finally:
            # Restore the old module or remove the module that was just
            # loaded from `sys.modules` only if we do not load the module
            # globally.
            if not load_globally:
                if prev_module:
                    sys.modules[name] = prev_module
                else:
                    del sys.modules[name]

Comments

0

I'm using localimport now:

with _localimport('lib', eggs=True) as importer:
    import some_package
assert 'some_package' not in sys.modules
assert 'some_package' in importer.modules

https://github.com/NiklasRosenstein/localimport

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.