1

I am creating a project with so many modules, each module has helpers.py file that uses some functions from that file. here is my directory structure:

│ main.py ├───modules │ │ __init__.py │ ├───main │ │ main.py │ │ __init__.py │ │ │ ├───network │ │ │ helpers.py │ │ │ network.py │ │ │ __init__.py │ │ 

main.py:

from modules.main import main if "__main__" == __name__: main() 

modules/main/main.py:

import sys sys.path.insert(0, 'J:\\Scanner\\modules') import network.network as HostDiscovery 

modules/network/network.py:

from helpers import ips ... 

Whenever I try to run main.py in the root directory, I get the error:

from helpers import ips ModuleNotFoundError: No module named 'helpers' 

Each module works fine when I try running it alone, but when I run from main.py it fails with the error that it cant find helpers module. How can I achieve this without having to change the directory structure.

4
  • BTW, there is no good reason to "reverse" comparisons to a constant like that in Python. Accidentally writing = would be a syntax error, and there are no "null pointers" to worry about - None == 'foo' simply (and correctly) evaluates to False. Commented Mar 1, 2022 at 1:46
  • Anyway, seriously, you want to use relative imports for this. Commented Mar 1, 2022 at 1:47
  • Hi @KarlKnechtel, the way I see it is actually I would rather get a syntax error than a logical error. care to explain more? Commented Mar 4, 2022 at 8:11
  • In Python, you will get a syntax error rather than a logical error, whether or not you reverse the condition; so there is no reason to reverse the condition. In Python's grammar, = is part of an assignment statement, which is not a kind of expression (unlike C and C++ where assignments are a kind of expression). Commented Mar 5, 2022 at 23:29

2 Answers 2

1

I can think of two ways to solve.

  1. add source root to sys.path to top of every main file

Whenever you want to import something, the import path should start from the root. Of course some directory tranversing might be necessary because you don't want hardcode the root path, right?

This is a common practice for ISE such as pycharm, which has an option to let you add source root to path(when running from pycharm), and the option is needed for intellisense to work.

  1. try relative import

such as from .foo import bar, or from ..foo import bar. I think you need read docs yourself.

Sign up to request clarification or add additional context in comments.

4 Comments

Relative imports are almost always the best option here... adding to the path can potentially break other code, since it applies to all of your Python program, rather than just one module, and will also apply to all other programs that your program started. Always use relative imports where you can.
one drawback, i can think of, is you need change relative import when you refactor your folder structure.
VS Code's Python extension will handle this for you, and I imagine PyCharm is going to do the same
works fine with relative import. thanks!
0

I guess you can add to the Python path at runtime:

# some_file.py import sys # insert at 1, 0 is the script path (or '' in REPL) sys.path.insert(1, '/path/to/application/app/folder') import file 

Dunno if this helps, I'm new to Python.

1 Comment

Adding to the path is almost always a bad idea, since it can affect code outside of your own. You should always do so with extreme caution, and use relative imports where possible

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.