Question

I have a python script that is trying to import another script somewhere in the file-system (path is only known at runtime). To my understanding I need to use the imp module and this might work, but when loading the module I get an error that modules used by the imported module are not found.

Heres the code:

importer.py:

import imp
imp.load_compiled("my_module","full_path_to_my_module\\my_module.pyc")

my_module.py:

import sys
import another_module

When I run importer.py I get htis error message:

ImportError: No module named another_module

Whats going wrong here ? I suspect that when 'importer.py' is loading 'my_module.pyc' hes also trying to load 'another_module' (thats good) but is looking in the wrong place (eg not 'full_path_to_my_module')

EDIT: I tried adding 'full_path_to_my_module' to the system path:

import imp
import sys

sys.path.append(full_path_to_my_module)
imp.load_compiled("my_module",full_path_to_my_module+my_module)

But I still get the same error

Maybe I do something thats not necessary - Here's my goal: I want to be able to use all functionality of 'my_module.pyc' inside 'importer.py'. But the location of 'my_module.pyc' is given as a parameter to 'importer.py'.

Was it helpful?

Solution

imp.load_compiled returns the compiled module object, it is different to the import statement which also binds the module to a name

import imp
my_module = imp.load_compiled("my_module", "full_path_to_my_module/my_module.pyc")

Then you can do something like:

my_module.yayfunctions('a')

Complete example session:

$ cat /tmp/my_module.py
def yayfunctions(a):
    print a
$ python -m compileall /tmp/my_module.py
$ ls /tmp/my_module.py*
my_module.py   my_module.pyc
$ python
>>> import imp
>>> my_module = imp.load_compiled("my_module", "/tmp/my_module.pyc")
>>> my_module.yayfunctions('a')
a

Edit regarding comment (ImportError: No module named another_module), I assume the error is caused by the code in my_module.pyc, and the another_module.py lives in the same directory

In that case, as others have suggested, it's simpler to just add the directory containing my_module to sys.path and use the regular import mechanism, specifically __import__

Here's a function which should do what you want:

import os


def load_path(filepath):
    """Given a path like /path/to/my_module.pyc (or .py) imports the
    module and returns it
    """

    path, fname = os.path.split(filepath)
    modulename, _ = os.path.splitext(fname)

    if path not in sys.path:    
        sys.path.insert(0, path)

    return __import__(modulename)


if __name__ == '__main__':
    # Example usage
    my_module = load_path('/tmp/my_module.py')
    my_module.yayfunctions('test')

OTHER TIPS

It is since at the scope of import another_module your "full_path_to_my_module" isn't known.

Have you tried to add the path to known paths instead, i.e.:

import sys
sys.path.append("full_path_to_my_module")

You don't actually need to use the imp module to load pyc modules.

An easy way to try it out is to make two python modules, one importing from the other and run it. Delete then the imported .py file so you only get the .pyc file left: when running the script the import will work just fine.

But, for importing py files from random directories, you may want to add that directory to the python path first before importing it.

For instance:

import sys
sys.path.insert(0, "/home/user/myrandomdirectory")

Loading pyc files works the exact same way as loading a py file except it doesn't do a compile step. Thus just using import mymodule will work as long as the version number of the pyc is the same as the python you're running. Otherwise you'll get a magic number error.

If you module isn't in your path you'll need to add that to sys -- or if its a subdirectory, add a __init__.py file to that directory..

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top