How do I import a Python script from a sibling directory?
Asked Answered
T

5

103

Let's say I have the following directory structure:

parent_dir/
    foo_dir/
        foo.py
    bar_dir/
        bar.py

If I wanted to import bar.py from within foo.py, how would I do that?

Titi answered 22/4, 2012 at 22:57 Comment(1)
See: https://mcmap.net/q/14224/-sibling-package-imports/…Weiser
F
58

If all occurring directories are Python packages, i.e. they all contain __init__.py, then you can use

from ..bar_dir import bar

If the directories aren't Python packages, you can do this by messing around with sys.path, but you shouldn't.

Falbala answered 22/4, 2012 at 23:0 Comment(7)
this will not work if you want to import in a non package and you just run a python from a sibling. In this case sys.path.append is the way to goMaterialism
@Materialism I'd say in this case you have done something wrong, but if it's just some hacky script it might be OK to mess around with sys.path.Falbala
Its not wrong but when running the main module you cannot do relative imports. python.org/dev/peps/pep-0366Materialism
When I run ipython foo.py on this, I get ImportError: attempted relative import with no known parent package. I've added an __init__.py file to the parent directory and the bar_dir directoryBenzocaine
@ogogmad, did you find a solution to this? ThanksHumming
Just like @ogogmad, running it with python3 also gives the same error. ImportError: attempted relative import with no known parent packageLumpen
This does work in Python 3.8, but requires that the parent package is accessible to Python, and that the module is imported as part of that package. I should probably expand this answer a little, but don't have time to do so.Falbala
T
47

You can use the sys and os modules for generalized imports. In foo.py start with the lines

import sys
import os
sys.path.append(os.path.abspath('../bar_dir'))
import bar
Tesstessa answered 22/4, 2012 at 23:1 Comment(2)
Note that this will use the sibling directory of the cwd, not the sibling directory of where foo.py is. To use the script's directory, use sys.path.append(os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'bar')))Mechellemechlin
The only thing that worked on this entire page.Aubine
J
4

Let's say if you have following structure:

root
  |_ productconst.py
  |_ products
     |_ __init__.py

And if you would like to import productconst in products.__init__, then following can be used :

from ..productconst import * 
Jimjams answered 16/1, 2022 at 17:50 Comment(0)
L
0

If you're having issues in python 3+, the following worked for me using sys.path.append("..").

sys.path.append("..")
from bar_dir import bar
Lefkowitz answered 27/9, 2021 at 15:22 Comment(0)
P
0

Most of the proposed answers have relied on altering sys.path. IMHO - this is not neccessary if you can retain the relative folder structure correctly. I was inspired by the response of a similar question:

Please see my worked out example below. I have followed the same folder structure as in your question

Folder structure

enter image description here

After expanding the folder parent_dir

enter image description here

bar_dir/bar.py

The file bar.py implements a skeletal class Bar

class Bar():
    def __init__(self) -> None:
        pass

    def __repr__(self) -> str:
        return "This is an instance of Bar"
    
    def some_method(self) ->None:
        pass

bar_dir/init.py

from .bar import Bar

foo_dir/foo.py

The file foo.py implements a simple class Foo which in turn references the class Bar through a constructor parameter.

from ..bar_dir import Bar

class Foo():
    def __init__(self ,bar_instance: Bar) -> None:        
        self._bar=bar_instance

    def __repr__(self) -> str:
        return f"You are inside an instance of Foo and you have just accessed bar={self._bar}"

foo_dir/init.py

from .foo import Foo

sfo_main.py

This is main runner script which glues together foo_dir and bar_dir packages

import parent_dir.bar_dir as bar_lib
import parent_dir.foo_dir as foo_lib


if __name__ == "__main__":
    f=foo_lib.Foo(bar_instance=bar_lib.Bar())
    print(f"This is an instance of foo={f}")
    print(f"{bar_lib.Bar()}")

Output from sfo_main.py

enter image description here

Why use a init.py ?

https://docs.python.org/3.9/tutorial/modules.html

Documentation on relative imports

https://docs.python.org/3/reference/import.html

Pavkovic answered 1/3, 2024 at 23:38 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.