1

So I am working on implementing a file structure to my Python and am having an error with doing imports. The file structure looks something like this:

Dirs(Folder)
   ╘ run.py
     Vers(Folder)
        ╘ __init__.py
          1_1(Folder)
             ╘ Main.py
               secondary.py
               __init__.py
          1_2(Folder)
             ╘ Main.py
               secondary.py
               __init__.py

This is the contents of run.py

import importlib
print("This is the main module")
A = importlib.import_module(str("Vers.1_1.Main"))
A.start()
B = importlib.import_module(str("Vers.1_2.Main"))
B.start()

Each Main.py and secondary.py contain code that is the same except for the version number in the print statements, which is changed depending on the version number of the folder they are in.

Main.py

import secondary
class start():
    def __init__(self):
        print("This is version 1.2 main")
        secondary.start()

secondary.py

class start():
    def __init__(self):
        print("This is version 1.1 secondary")

This is the output I get when I execute run.py

This is the main module
Traceback (most recent call last):
  File "Python\Python36-32\lib\importlib\__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 978, in _gcd_import
  File "<frozen importlib._bootstrap>", line 961, in _find_and_load
  File "<frozen importlib._bootstrap>", line 950, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 655, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 205, in _call_with_frames_removed
  File "Dirs\Vers\1_1\Main.py", line 1, in <module>
import secondary
ModuleNotFoundError: No module named 'secondary'

So from my understanding, run.py is able to successfully find and attempt to import Main.py from the 1_1 Folder. However, when executing the Main.py file, it is unable to see that secondary.py is in the same directory to import it. I've tried looking for how to fix this problem, but I really don't know what my issue is. Is how I am attempting to set up packages wrong? If so what do I need to change in order to make it work properly?

Skitzafreak
  • 1,797
  • 7
  • 32
  • 51

2 Answers2

1

Short answer: Use

from . import secondary

Longer version: It looks like you assume Python 2 relative import semantics, when this is Python 3 with absolute import semantics. Have a look e.g. here for a more detailed explanation.

If you do

import secondary

this is an absolute import, and thus is not resolved relative to the current package, but rather from sys.path.

When you execute run.py as a Python script (not as a module with -m), the directory the script resides in gets added to sys.path automatically, which is why importing Vers.1_1.Main works, but import secondary does not.

dhke
  • 15,008
  • 2
  • 39
  • 56
  • Thank you very much. This is probably my best solution since I don't want to have to modify all the import statements every time I great a new version directory :P – Skitzafreak Dec 14 '17 at 19:50
  • @Skitzafreak ... which is exactly one reason why there are those nice explicit relative imports ;-). – dhke Dec 14 '17 at 19:52
  • One question though. Let's say I had an import like `from Mod import ClassA`. How would I change that to the `from . import` notation? Does `from . import Mod.ClassA` work? – Skitzafreak Dec 14 '17 at 19:53
  • @Skitzafreak `from .Mod import ClassA`. `from ... import` only allows you to import submodules directly, not as submodules (unless the outer module does that for you). – dhke Dec 15 '17 at 10:00
0

After the import your code is executing under Dirs, where there is no secondary module to import

Change

import secondary

in Main.py

to

import Vers.1_1.secondary

and to

import Vers.1_2.secondary

in the other Main.py

progmatico
  • 4,714
  • 1
  • 16
  • 27