trying to import a *.pyc as a module

AntiZamba picture AntiZamba · Aug 23, 2012 · Viewed 13.1k times · Source

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'.

Answer

dbr picture dbr · Aug 23, 2012

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')