1

I've made a minimal example project to attempt to resolve my module imports issue. The structure is as follows:

MyProject/
├── main.py
└── utils/
    ├── __init__.py
    ├── foo.py
    └── bar.py

main.py only contains this code: from utils import foo

__init__.py does not contain any code

foo.py only contains this code: from bar import Bar

bar.py only contains this code: class Bar: pass

If I run python utils/bar.py, it runs with no exceptions.

Similarly, if I run python utils/foo.py, it runs with no exceptions.

However, if I run python main.py, it results in the following exception: ModuleNotFoundError: No module named 'bar'

Is there any way to resolve this issue? Or is it even an issue, perhaps I'm doing something I'm not supposed to?

Nevermore
  • 318
  • 2
  • 11
  • 1
    `from .bar import Bar` ? – jmbarbier Sep 19 '21 at 21:16
  • That fixed the ability to run main.py, but if I try to run foo.py, I get a new error: "ImportError: attempted relative import with no known parent package" – Nevermore Sep 19 '21 at 21:20
  • 1
    ``` try: from .bar import Bar except ImportError: # python3 from bar import Bar except ValueError: # python2 from bar import Bar ``` – jmbarbier Sep 19 '21 at 21:21
  • That worked! Thanks! Interesting though... is that standard practice for this sort of thing? – Nevermore Sep 19 '21 at 21:25
  • 1
    Calling "subpackage" and "mainpackage" is not really a standard practice, neither. There may be other maybe cleaner ways avoiding these except, by tweaking python modules search path in main.py for example : https://stackoverflow.com/questions/16981921/relative-imports-in-python-3?rq=1 – jmbarbier Sep 19 '21 at 21:30
  • Thanks for the link, lots to unpack there. I've always called my submodules for unit testing purposes, for example in foo.py I might have an ```if __name__ == "__main__": run_tests()``` but it seems like this behavior may not be the "correct" or "intended" way of doings things after all. – Nevermore Sep 19 '21 at 21:38

1 Answers1

1

If you want to use it as a standalone call (python utils/foo.py) and from main (python main.py), you can use both imports :

try:
    from .bar import Bar
except ImportError: # for python3
    from bar import Bar
except ValueError: # for python2
    from bar import Bar
jmbarbier
  • 814
  • 8
  • 21