Importing from above path on python for windows

Solution 1:

The proper way to handle this would be putting everything that needs to know about each other under a shared package, then the individual sub-packages and sub-modules can be accessed through that package. But this will also require moving the application's entrypoint to either the package, or a module that's a sibling of the package in the directory and can import it. If moving the entrypoint is an issue, or something quick and dirty is required for prototyping, Python also implements a couple other methods for affecting where imports search for modules which can be found near the end of the answer.

For the package approach, let's say you have this structure and want to import something between the two modules:

.
├── bar_dir
│   └── bar.py
└── foo_dir
    └── foo.py

Currently, the two packages do not know about each other because Python only adds the entrypoint file's parent (either bar_dir or foo_dir depending on which file you run) to the import search path, so we have to tell them about each other in some way, this is done through the top level package they'll both share.

.
└── top_level
    ├── __init__.py
    ├── bar_dir
    │   ├── __init__.py
    │   └── bar.py
    └── foo_dir
        ├── __init__.py
        └── foo.py

This is the package layout we need, but to be able to use the package in imports, it has to be initialized, which means we either need to import the top_level package (e.g. from a main.py entrypoint), or define it as a runnable module by implementing a __main__.py file inside of it, next to __init__.py, which is ran when doing python -m top_level. This entrypoint module would then run the module which you were running beforehand.

The __init__.py files are used to mark the directories as proper packages and are ran when the package is imported to initialize its namespace.

With this done the packages now can see each other and can be accessed through either absolute or relative imports, an absolute import would being with the top_level package and use the whole dotted path to the module/package we need to import, e.g. from top_level.bar_dir import bar can be used to import bar.

Packages also allow relative imports which are a special form of a from-style import that begins with one or more dots, where each dot means the import goes up one package - from the foo module from . import module would attempt to import module from the foo_dir package, from .. import module would search for it in the top_level package etc.

One thing to note is that importing a package doesn't initialize the modules under it unless it's an explicit import of that module, for example only importing top_level won't make foo_dir and bar_dir available in its namespace unless they're imported directly through import top_level.foo_dir/top_level.bar_dir or the package's __init__.py added them to the package's namespace through its own import.


If this doesn't work in your structure, an another way is to let Python know where to search for your modules by adding to its module search path, this can be done either at runtime by inserting path strings into the sys.path list, or through the PYTHONPATH environment variable.

Continuing with the above example with a scenario and importing bar from foo, an entry for the bar_dir directory (or the directory above it) can be added to the sys.path list or the aforementioned environment variable. After that import bar (or from bar_dir import bar if the parent was added) can be used to import the module, just as if they were next to each other. The inserted path can also be relative, but that is prone to breakage with a changing cwd.