0

I found a lot of similar questions, but no one gave any answer. Still doesn't work.

My current structure:

Project: 
- exp: 
   -- main.py
- mypac: 
   - internal: 
      -- __init__.py
      -- next_mod.py
   -- __init__.py
   -- file.py

../Project/mypac/__init__.py:

from .internal.next_mod import print_smth

../Project/mypac/internal/next_mod.py:

def print_smth():
    print(f'{__name__} from another module')

../Project/exp/main.py:

from mypac import print_smth

print_smth()

I tried lot of different approaches, but nothing prevent from error:

ModuleNotFoundError: No module named 'mypac'
  1. sys.path.append('../mypac') - not working
  2. sys.path.abspath + dir + __file__ - not working
  3. VS code JSON launch PYTHONPATH config - not working

and the rest i found at SOF.

Can anyone help me to figure out what the mistake?

S.B
  • 13,077
  • 10
  • 22
  • 49
calm27
  • 145
  • 6
  • 1
    Try `from mypac.file` and/or [read this](https://realpython.com/python-import/) for more info and examples. – not2savvy Apr 02 '23 at 08:28
  • @not2savvy If it complained about finding `'mypac'` module on that form, it would also complains here because `from mypack.file` also tries to locate `mypac` first. – S.B Apr 02 '23 at 08:46
  • Yes, sorry, main.py should be in the top folder, as also mentioned in the answers now. – not2savvy Apr 02 '23 at 10:16

3 Answers3

1

One easy solution is to run main.py as a module from the Project directory:

~/Project> python -m exp.main
mypac.internal.next_mod from another module

Alternatively, you can add the Project directory to the path (not the mypac directory). By using pathlib and __file__ you can even make it independent of the actual name and location of the directory.

import sys, pathlib
# Add Project/ dir to path.
sys.path.append(str(pathlib.Path(__file__).parent.parent.absolute()))

from mypac import print_smth
print_smth()
# mypac.internal.next_mod from another module
BoppreH
  • 8,014
  • 4
  • 34
  • 71
  • works as well! i need to take a look what is the difference between running as a module and as a script. – calm27 Apr 02 '23 at 09:17
1

You're running main.py module as the entry point. By default Python inserts "its" directory which is .....Project/exp to the sys.path.

It knows nothing about mypac directory. In order to let him know about it, you need to manually add "its" directory to the sys.path which is the Project directory.

Add the following before your import statement: (Use absolute path instead of placeholders)

import sys
sys.path.insert(0, ".....Project/")

from mypac import print_smth

print_smth()  # mypac.internal.next_mod from another module

You could also add this directory using PYTHONPATH environment variable and run your script like:

PYTHONPATH='....Project/' python main.py
S.B
  • 13,077
  • 10
  • 22
  • 49
  • finally, an approach that works, but so far as i know, it is a good practice to avoid using *sys* for importing. is there some alternative way how to build importing path without directly using 'sys.path.insert/append'? – calm27 Apr 02 '23 at 09:13
  • 1
    @calm27 Yes it's correct. The problem comes from how your folder structure is and how you import your modules. I tried to give a solution to the current state. Usually your entry point should be at the root of your project to be sure that the root is on the path. In other submodule/packages your should import your modules according to this root path and everything works well. Now your entry point is not on the root but your import statements are addressing the module from the root. – S.B Apr 02 '23 at 09:18
1

I would not recommend using sys.path.insert... to make this code work. Instead create a setup.py file and install your package correctly. You can view this question as a reference point - What is setup.py?

Barak Fatal
  • 158
  • 8