miro_x
miro_x

Reputation: 201

Python module importing with sys.path and os.path issue

I spent some time researching this and I just cannot work this out in my head.

I run a program in its own directory home/program/core/main.py

In main.py I try and import a module called my_module.py thats located in a different directory, say home/program/modules/my_module.py

In main.py this is how I append to sys.path so the program can be run on anyone's machine (hopefully).

import os.path
import sys

# This should give the path to home/program
sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__), '..'))
# Which it does when checking with
print os.path.join(os.path.abspath(os.path.dirname(__file__), '..')

# So now sys.path knows the location of where modules directory is, it should work right?

import modules.my_module # <----RAISES ImportError WHY?

However if I simply do:

sys.path.append('home/program/modules')
import my_module

It all works fine. But this is not ideal as it now depends on the fact that the program must exist under home/program.

Upvotes: 4

Views: 7566

Answers (2)

Ataxias
Ataxias

Reputation: 1193

Although the answer can be found here, for convenience and completeness here is a quick solution:

import importlib

dirname, basename = os.path.split(pyfilepath) # pyfilepath: /my/path/mymodule.py
sys.path.append(dirname) # only directories should be added to PYTHONPATH
module_name = os.path.splitext(basename)[0] # /my/path/mymodule.py --> mymodule
module = importlib.import_module(module_name) # name space of defined module (otherwise we would literally look for "module_name")

Now you can directly use the namespace of the imported module, like this:

a = module.myvar
b = module.myfunc(a)

Upvotes: 1

Jean-Fran&#231;ois Fabre
Jean-Fran&#231;ois Fabre

Reputation: 140168

that's because modules isn't a valid python package, probably because it doesn't contain any __init__.py file (You cannot traverse directories with import without them being marked with __init__.py)

So either add an empty __init__.py file or just add the path up to modules so your first snippet is equivalent to the second one:

sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__), '..','modules'))
import my_module

note that you can also import the module by giving the full path to it, using advanced import features: How to import a module given the full path?

Upvotes: 1

Related Questions