ModuleNotFoundError when running script from Terminal
You probably want to run python -m products.fish
. The difference between that and python products/fish.py
is that the former is roughly equivalent to doing import products.fish
in the shell (but with __name__
set to __main__
), while the latter does not have awareness of its place in a package hierarchy.
This expands on @Mad Physicist's answer.
First, assuming app
is itself a package (since you added __init__.py
to it) and utils
and products
are its subpackages, you should change the import to import app.utils.transform
, and run Python from the root directory (the parent of app
). The rest of this answer assumes you've done this. (If it wasn't your intention making app
the root package, tell me in a comment.)
The problem is that you're running app.products.fish
as if it were a script, i.e. by giving the full path of the file to the python
command:
python app/products/fish.py
This makes Python think this fish.py
file is a standalone script that isn't part of any package. As defined in the docs (see here, under <script>
), this means that Python will search for modules in the same directory as the script, i.e. app/products/
:
If the script name refers directly to a Python file, the directory containing that file is added to the start of
sys.path
, and the file is executed as the__main__
module.
But of course, the app
folder is not in app/products/
, so it will throw an error if you try to import app
or any subpackage (e.g. app.utils
).
The correct way to start a script that is part of a package is to use the -m
(module) switch (reference), which takes a module path as an argument and executes that module as a script (but keeping the current working directory as a module search path):
If this option is given, [...] the current directory will be added to the start of
sys.path
.
So you should use the following to start your program:
python -m app.products.fish
Now when app.products.fish
tries to import the app.utils.transform
module, it will search for app
in your current working directory (which contains the app/...
tree) and succeed.
As a personal recommendation: don't put runnable scripts inside packages. Use packages only to store all the logic and functionality (functions, classes, constants, etc.) and write a separate script to run your application as you wish, putting it outside the package. This will save you from this kind of problems (including the double import trap), and has also the advantage that you can write several run configurations for the same package by just making a separate startup script for each.