0

I have the following folder structure:

controller/
    __init__.py
    reactive/
        __init__.py
        control.py
pos/
    __init__.py
    devices/
        __init__.py
        cash/
            __init__.py
            server/
                __init__.py
                my_server.py
    dispatcher/
        __init__.py
        dispatcherctrl.py

I need to import the module control.py in my_server.py, but it say ImportError: No module named controller.reactive.control despite the fact that I have added __init__.py in all the folders and sys.path.append('/home/other/folder/controller/reactive') in my_server.py.

The main file is in my_server.py.

I don't understand why, because dispatcherctrl.py do the same import and it work fine.

k4ppa
  • 4,122
  • 8
  • 26
  • 36
  • Where is `orkit` in your module tree? –  Mar 11 '16 at 10:33
  • Edited the name with the correct one. – k4ppa Mar 11 '16 at 10:34
  • 3
    Try `sys.path.append('/home/other/folder/')`. –  Mar 11 '16 at 10:37
  • You're supposed to import `reactive` and define `control` in the `__init__.py` file. You can either do `sys.path.insert(0, '/path/to/controller/` and then do `import reactive` and call control via `reactive.control()`. – Torxed Mar 11 '16 at 10:42
  • @LutzHorn `sys.path.insert(0, ...)` instead to avoid something else overriding the desired functions by existing earlier in `PATH`. With a disclaimer that this might break built-ins : ) – Torxed Mar 11 '16 at 10:50

1 Answers1

1

In Python3

You could use the importlib.machinery module to create a namespace and absolute paths for your imports:

import importlib.machinery

loader = importlib.machinery.SourceFileLoader('control', '/full/path/controller/reactive/control.py')
control = loader.load_module('control')

control.someFunction(parameters, here)

This method can be used to import stuff in whatever way you want in any folder structure (backwards, recursively - doesn't really matter, i use absolute paths here just to be sure).

Python2

Kudos to Sebastian for supplying a similar answer for Python2:

import imp

control = imp.load_source('module.name', '/path/to/controller/reactive/control.py')
control.someFunction(parameters, here)

Cross version way

You can also do:

import sys
sys.path.insert(0, '/full/path/controller')

from reactive import control # <-- Requires control to be defined in __init__.py
                                                # it is not enough that there is a file called control.py!

Important! Inserting your path in the beginning of sys.path works fine, but if your path contains anything that collides with Python's built in functions, you will break those built in functions and it might cause all sorts of problems. There for, try to use the import mechanisms as much as possible and fall-back to the cross-version way of things.

Community
  • 1
  • 1
Torxed
  • 22,866
  • 14
  • 82
  • 131