42

I have a Python class called "ClassA" and another Python class which is supposed to import ClassA which is "ClassB". The directory structure is as follows:

MainDir
../Dir
..../DirA/ClassA
..../DirB/ClassB

How would I use sys.path so that ClassB can use ClassA?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
skylerl
  • 4,030
  • 12
  • 41
  • 60
  • 2
    It's called relative imports and has quite a bit of googleable material and SO questions. –  Dec 27 '10 at 22:43
  • http://stackoverflow.com/questions/279237/python-import-a-module-from-a-folder – jgritty Dec 27 '10 at 22:45

3 Answers3

53

as a literal answer to the question 'Python Import from parent directory':

to import 'mymodule' that is in the parent directory of your current module:

import os
parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
os.sys.path.insert(0,parentdir) 
import mymodule

edit Unfortunately, the __file__ attribute is not always set. A more secure way to get the parentdir is through the inspect module:

import inspect
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
Remi
  • 20,619
  • 8
  • 57
  • 41
  • 1
    Remi - Thanks for the literal answer. I found this useful when writing test code for a python app. I can place the test code in a subdirectory, and I can begin to put tests in place without modifying the existing project. (In other words; converting the existing code to a module before having tests in place would be the incorrect order to do things from the perspective of managing the risk of introducing bugs to working code.) Your method of changing the module path is handy. – Heath Hunnicutt Jul 21 '13 at 14:14
30

You can use relative import (example from link, current module - A.B.C):

from . import D                 # Imports A.B.D
from .. import E                # Imports A.E
from ..F import G               # Imports A.F.G
crazylammer
  • 1,152
  • 8
  • 7
  • 4
    @Yakattak: Yes, but they should be in a package anyway ;) –  Dec 27 '10 at 23:03
  • this looks like the best and simplest answer – Rabih Kodeih Sep 20 '12 at 18:00
  • 5
    caution: relative imports rely on `__name__` of modules, so if you ever intend to run the current module (which sets `__name__` to `__main__`), the relative imports will fail – Yibo Yang Apr 29 '17 at 07:30
  • What are the critera for calling it a package? Just that each of the subfolders contains an __init__.py? – Sledge Aug 07 '19 at 17:27
  • @Sledge It means **all three of** 1) putting an `__init__.py` in the top directory of your code **and** 2) adding the parent directory of the top dir to your `PYTHONPATH` **and** 3) setting the `__package__` variable in your Python program to the name of the directory that contains `__init__.py`. – AstroFloyd May 20 '21 at 14:05
17

You really should be using packages. Then MainDir is placed at a point in the file system on sys.path (e.g. .../site-packages), then you can say in ClassB:

from MainDir.Dir.DirA import ClassA # which is actually a module

You just have to place files named __init__.py in each directory to make it a package hierarchy.

Keith
  • 42,110
  • 11
  • 57
  • 76
  • I added MainDir to the sys.path and tried your solution, but it just says there is no module named MainDir.Dir.DirA, and there are __init__.pys in all directories. – skylerl Dec 28 '10 at 00:20
  • 3
    Don't add MainDir, add its parent directory. If you add MainDir (if that is not the package root, that is fine), then import like `from Dir.DirA import ClassA` instead. – Keith Dec 28 '10 at 01:18
  • It took me a while to figure out that "turning your code into a package" means **all of** 1) putting an `__init__.py` in the top dir of your code **and** 2) adding the parent directory of the top dir to your `PYTHONPATH` **and** 3) setting the `__package__` variable in your Python program to the name of the directory that contains `__init__.py`. All is working now, thanks! – AstroFloyd May 20 '21 at 11:48
  • if ClassA.py code defines `import ClassAA` where ClassAA.py is also in DirA, then the above method fails when ClassA is imported from ClassB. What is the correct way in this situation? – Phoenix Aug 03 '21 at 14:34
  • @Phoenix Use a relative import `import .ClassAA`, or in ClassB `import ..DirA.ClassAA`. – Keith Aug 05 '21 at 15:21