Skip to content
Advertisement

Being forced to import files relative to main.py in python

I’ve read several links about this but haven’t been able to find something that addresses my situation.

Here’s my directory structure:

- app

  - __init.py
  - main.py

  - foo
    - __init.py
    - foo_library.py

  - bar
    - __init.py
    -  bar_library.py

My application starts in main.py which in turn imports / calls all the other files.

However, it seems that I must import all files relative to main.py.

E.g inside foo/foo_library, if I want to import bar/bar_library, then I can’t do from ..bar import bar_library, or import app.bar.bar_library.

Instead I must do import bar.bar_library.py – i.e the path that would work if I was importing it from main.py instead of foo/foo_library.py.

Is there any way to use import app.bar.bar_library or from ..bar import bar_library?

Advertisement

Answer

Relative imports only work within a single package. In your example, you have a package app with subpackages foo and bar. As long as a script or module imports app (e.g., import app), then modules in foo and bar can do relative imports.

Scripts are not in packages. This is the same model used generally with executables where the operating system is tasked with finding static dynamic libraries in a common LIB directory. So main.py has no inherent knowledge of the app package.

When python runs a script, it adds its path the sys.path so any module or directory in that path can be imported. In your case, main.py can import foo and import bar. But if you do that, foo and bar are separate packages and relative imports won’t work between them.

You can solve the problem by moving main.py up one directory so that it can import app. More generally, you could move main.py into a script directory in your source tree and wrap your package + scripts into an installable distribution.

Another popular option when making a package installable, is to add entry point declarations to setup.py. The installer will add small dummy files in the operation system path that essentaily do python3 -m app.main to run the module within the package. Done this way, main.py is a part of the package and can do relative imports.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement