(Yet Another) 'ImportError: No module named my_module'

Viewed 91

Ok, I stripped the code to ultra minimal to illustrate the problem and make it reproducible

context :

  • Python 3.7
  • No VENV or funny stuff

Talk is cheap. Show you the code :

code structure :

$ tree pymod/
pymod/
├── modone
│   ├── __init__.py
│   └── one.py
└── modtwo
    ├── __init__.py
    └── two.py

init.py is everywhere where it should be, obviously

one.py :

from modtwo import two
class One():
    @staticmethod
    def print_one():
        print("this is one")
        two.print_two()

if __name__ == "__main__":
    One().print_one()

two.py :

class Two():
    @staticmethod
    def print_two():
        print("this is from two")

error thrown

$ python modone/one.py

Traceback (most recent call last):
  File "modone/one.py", line 1, in <module>
    from modtwo import two
  ImportError: No module named modtwo

What I tried so far :

  • Appended every possible directory to PYTHONPATH
  • ran the command from project root and relative paths
  • scratched my head compulsively

EDIT AFTER ANSWERS :

What I've learned so far :

  • modules and scripts are two different concepts. they are like the light wave/particle duality
    they should hence be called/treated as such (either as a module, or a script)

  • a module can be run as a script, but it won't be aware of the directory structures around it

2 Answers

Once you have a package-like directory structure, run python with the -m option to run a module as a script:

python -m modone.one

Also there is a bug in your one.py. You call print_two on the module you imported, not on the class inside the module.

The problem is how you're calling the print_two method. You called two, which is a module, that's why you got "module is not callable"

from modtwo import two
class One():
    @staticmethod
    def print_one():
        print("this is one")
        two().print_two()

You should access the class first

from modtwo import two
class One():
    @staticmethod
    def print_one():
        print("this is one")
        two.Two.print_two()

And run the script like this

python -m modone.one

The result is:

this is one
this is from two
Related