There is such a file structure:

root |--project1 | |--__init__.py | |--subrunner.py | |--proc.py |--project2 |--projectN |--runner.py 

runner.py

 from project1.subrunner import foo foo() 

subrunner.py

This version of import:

 from proc import bar def foo(): bar() 

allows you to run a subrunner , but when you run runner we get the error: ModuleNotFoundError: No module named 'proc' .
And this version of import:

 from .proc import bar 

relative through the dot, vice versa. Allows you to run the runner , but when you start the subrunner we get the error: ModuleNotFoundError: No module named '__main__.proc'; '__main__' is not a package ModuleNotFoundError: No module named '__main__.proc'; '__main__' is not a package

How to do the import correctly, so that it works both when the runner started and when the subrunner started?

    2 answers 2

    The "correct" version is:

     from .proc import bar 

    At the same time, the subrunner looks like this for me:

     from .proc import bar def foo(): print('foo') bar() if __name__ == '__main__': foo() 

    You need to run subrunner with the -m interpreter:

     python -m project1.subrunner 

    Displays:

     foo bar 
    • The problem is that initially, this is an independent, separate program, with the speaker name of the folder. For which the start is "outside", utils> python -m BookManager.manager , instead of utils\BookManager> python -m manager looks alien. But sometimes, they can be connected to other programs, in a role that resembles a plugin. I suppose that you need to write __init__ certain way, but I don’t know where to dig. - Lecron Sep.
    • For me, so python -m BookManager.manager looks quite normal, not much different, for example from python BookManager/manager.py . Matter of habit. Optionally, you can import into try - except ModuleNotFoundError can be wrapped. Also look at the answers to this question: stackoverflow.com/q/16981921/4752653 - insolor
    • one
      Thanks for the help and the link. try - except , despite the visual appeal, does not fit. The modules in the program can be more and the connection between them is more complicated. It is necessary to write a wrapper for each import. The problem was solved by writing standalone.py inside the directory, with the sys.path extension and relative import from project1.subrunner import foo , completely analogous to the runner-at the top level. - Lecron
    • Better yet, add the sys.path list sys.path to __init__.py , which will exclude any modifications to the original when (the usual absolute import remains) and writing wrappers, while using the program as a package. - Lecron
    • @Lecron, I think this can be done as an answer - insolor

    If you put such code in the __init__.py file of the Project1 directory:

     import os, sys sys.path.append(os.path.dirname(os.path.realpath(__file__))) 

    then when using the program as a package (running runner.py ), you do not have to edit the imports, keeping them absolute from proc import bar .