0

My current projects are structured like so.

python/
    __init__.py
    project_1/
        __init__.py
        program_1.py
    project_2/
        __init__.py
        program_2.py
    project_3/
        __init__.py
        program_3.py

I wanted to import a class from project_3/program_3.py, called INFO, from both project_1/program_1.py and project_2/program_2.py. In both my program_1.py and program_2.py, I've tried the following import statements that didn't work.

Edit - I typically "cd" into project_1 and run my program_1.py from there.

from project_3.program_3 import INFO

Traceback (most recent call last):
  File "./program_1.py", line 43, in <module>
    from project_3.program_3 import INFO
ImportError: No module named 'project_3'

from python.project_3.program_3 import INFO

Traceback (most recent call last):
  File "./program_1.py", line 43, in <module>
    from python.project_3.program_3 import INFO
ImportError: No module named 'python'

The only way for me to import class INFO into program_1.py and program_2.py is by copying program_3.py in both program_1 and program_2's folder. My import in program_1 and program_2's statement would become:

python/
    __init__.py
    project_1/
        __init__.py
        program_1.py
        program_3.py
    project_2/
        __init__.py
        program_2.py
        program_3.py
    project_3/
        __init__.py
        program_3.py

from program_3 import INFO

This is quite inconvenience because now I have to update program_3.py in all 3 locations. Assuming my the way I structured my project folder is retarded:

  • What's the correct/best way to structure my folders so that I could call program_3.py from program_1/2.py?
  • If there's nothing wrong with my current structure, how do I correctly import the INFO class into program_1/2.py?

I have read the python documentation but it didn't say anything regarding importing classes from one subfolder to another. I also looked at another post from Stack Overflow as well but it didn't have the same structure as mine.

Update 1 - It's important to note that I'm merely using project_1/2 as folder to organized my projects. I originally had init.py in all my folders because I have no clue what I'm doing. The only module/package that I wanted to import in my project_1/program_1.py is from project_3/program_3.py. Example:

python/
    project_1/
        program_1.py
    project_2/
        program_2.py
    project_3/
        __init__.py
        program_3.py
dreamzboy
  • 795
  • 15
  • 31
  • Change directory in each python script to the python root directory`os.chdir('./python')` and then handle imports from there – RandomHash May 22 '17 at 18:44

2 Answers2

1

When using submodules, you need to use relative imports. In the example provided, importing program_3 from program_1 should be :

from ..project_3 import program_3

and then you can use the INFO class: program_3.INFO.

This works if your executable file is outside the script, that is the file which uses the module python in the example should be outside the python module.

If parts of the python package are executed as a script, the -m option should be passed to the interpreter:

python3 -m python.project_1.program_1

I hope this helps.

Gerges
  • 6,269
  • 2
  • 22
  • 44
  • 1
    I did a bit differently but similar by doing "from ..project_3.program_3 import INFO". The error I got was "SystemError: Parent module '' not loaded, cannot perform relative import." – dreamzboy May 22 '17 at 18:52
  • Is the file you are running inside the module itself?. If this is the case, use `-m` option such as `python -m python.project_1.program_1` – Gerges May 22 '17 at 19:04
  • I typically cd into project_1 and run ./program_1.py from there. If I tried to run it with the -m option, I get the following error: python3.5 -m python.project_1.program_1.py /usr/local/bin/python3.5: Error while finding spec for 'python.project_1.program_1.py' (ImportError: No module named 'python') – dreamzboy May 22 '17 at 19:24
  • You need to cd to the directory which contains the outer module `python`, then you can run your program as in the updated answer. If you really want to run it from within program_1, you will need to change the path from within the program or something like that... – Gerges May 22 '17 at 19:31
  • 1
    @dreamzboy in general, directly executing code from within packages (folders that have an `__init__.py` within) is wrong and very likely to cause problems. – Nick T May 22 '17 at 19:37
  • @Nick, what's the proper way to run it or "mobilized" program_3.py to be used across my other projects? I guess I didn't understand the purpose of __init__.py; therefore, I removed it from python, project_1/2, and only kept it in project_3. The python, project_1/2, are just folders where I organized my python scripts. They're not module/packages. The only module/package that I wanted to use is project_3/program_3.py. – dreamzboy May 22 '17 at 20:58
0

The previous solution provides me the same error.

I found a fix by using sys:

import sys
sys.path.append('../')

from project_3 import program_3
...

This way, you setup 'python' folder as reference (in your case it's the parent folder but you can select the path you want)

I hope it helps,

Nicolas M.
  • 1,472
  • 1
  • 13
  • 26
  • I have updated my answer so that it works when running scripts within the module. – Gerges May 22 '17 at 19:12
  • Thanks. This works but of course PEP8 doesn't like the fact that the import statement is below the sys.path.append ('../') statement. It's definitely better than my work around but I prefer following the "standard" to keep things neat if there's an alternative. – dreamzboy May 22 '17 at 19:29
  • Unfortunately, it's the only solution I found on others forums. They provide more elegant way to define the path but it's the same fix. Please share if you got another solution (I'm also interested :) ) – Nicolas M. May 22 '17 at 19:38
  • I ended up doing the workaround where I moved my program_1/2.py under python/ directory and was able to use from project_3 import program_3.py with no errors. Your solution is definitely clever but in my opinion it's more of a hack than a solution. If I have different versions of program_1, I'll just move it back into the project_1 folder and continue to develop the original program_1 under the python directory. – dreamzboy May 24 '17 at 21:35