2

I am editing to minimize to a reproducible example:

Contents of cal.py

import M1

M1.SM1.nice_hello.hello()

Directory structure:

M1/
├── __init__.py
└── SM1
    ├── __init__.py
    └── nice_hello.py

Contents of SM1/nice_hello.py:

def hello():
    print(f'Hello my friend!!!')

All other files (init.py files) are empty.

To run cal.py:

export PYTHONPATH=/PATH/TO/M1 ; python cal.py

But that gives me following error:

Traceback (most recent call last):
  File "cal.py", line 3, in <module>
    M1.SM1.nice_hello.hello()
AttributeError: module 'M1' has no attribute 'SM1'
lllrnr101
  • 2,288
  • 2
  • 4
  • 15
  • Is cal.py at the same level as M1? – ctenar May 17 '21 at 07:01
  • How exactly do you run `cal.py`? From the command line? From what directory? – djvg May 17 '21 at 07:05
  • I do `export PYTHONPATH=/PATH/TO/M1` ; the I run using `python cal.py` – lllrnr101 May 17 '21 at 07:07
  • And where is cal.py in your directory structure? – djvg May 17 '21 at 07:17
  • cal.py can be anywhere, so long as PYTHONPATH is set, it should not matter. – lllrnr101 May 17 '21 at 07:20
  • May be so, but this is not mentioned in your question, and without that information, it is not reproducible. – djvg May 17 '21 at 07:33
  • updated and added. – lllrnr101 May 17 '21 at 07:39
  • 1
    I believe https://stackoverflow.com/a/8899345 answers your question, together with [section 6.4 from the Python docs](https://docs.python.org/3/tutorial/modules.html#packages). It also helps to check `sys.modules` to find out which modules have been loaded, and use [`dir()`](https://docs.python.org/3/tutorial/modules.html#packages) to see which names they define. – djvg May 17 '21 at 08:36

2 Answers2

1

It should work if you import the whole module name, i.e. in the file cal.py

import M1.SM1.nice_hello

M1.SM1.nice_hello.hello()
ctenar
  • 718
  • 5
  • 24
  • But why is M1 not able to use SM1, when it is inside it? – lllrnr101 May 17 '21 at 07:09
  • 1
    Submodules are not imported automatically, but you could generate this behaviour by doing a chain of imports in the respective ```__init__.py```-files. – ctenar May 17 '21 at 07:36
  • Is there any way to import Submodules when I import the MainModule. – lllrnr101 May 17 '21 at 07:38
  • In this example, when you include the line ```import M1.SM1.nice_hello``` in ```M1.__init__.py```, you can just import M1 in the main module and then call ```M1.SM1.nice_hello.hello()```. Alternatively, you can add ```import M1.SM1``` in ```M1/__init__.py``` and ```import M1.SM1.nice_hello``` in ```SM1.__init__.py```. – ctenar May 17 '21 at 07:50
1

Submodules are not imported recursively, if you want that to happen you can do the below: -

A) Create init.py file inside M1 module ( I think you already have that )

B) Have the below code in your init.py file : -

import importlib
import pkgutil

def import_submodules(package, recursive=True):
""" Import all submodules of a module, recursively, including subpackages

:param package: package (name or actual module)
:type package: str | module
:rtype: dict[str, types.ModuleType]
"""
if isinstance(package, str):
    package = importlib.import_module(package)
results = {}
for loader, name, is_pkg in pkgutil.walk_packages(package.__path__):
    full_name = package.__name__ + '.' + name
    results[full_name] = importlib.import_module(full_name)
    if recursive and is_pkg:
        results.update(import_submodules(full_name))
return results

This will help you import all the submodules inside that package ( M1)

Now in your cal.py do below: -

import M1
M1.import_submodules(M1)
def hello():
    print(f'Hello my friend!!!')

Hopefully this will resolve your issue and might guide you on how to import modules recursively in python

Reference :- How to import all submodules?

Please reach out in comments if any further clarification is required. Will be happy to help

Pratap Alok Raj
  • 1,098
  • 10
  • 19