As mentioned, to illustrate the difference in the paths used during your IDE execution and terminal execution, run the below script in both IDE and the terminal:
import os
import sys
print(os.getcwd())
for i in sys.path:
print(i)
Comparing the your results, when executing from the terminal, these folders are missing as compared to running in IDE:
'/home/myname/workspacep/problem2'
'/usr/lib/pymodules/python2.7'
A thing to note is that the current working directory and sys.path
s will change in terminal depending on where you run it from and where the file resides. But the key is sys.path
s because they tell python where to look for modules.
I'm willing to bet the modules you are attempting to import are from one of these folders, most likely under the /home/myname/workspacep/problem2
. This introduces issues as your modules are neither stored in a centralized access location (say, /usr/lib/python2.7/my_modules
) nor a subfolder under your project structure.
To illustrate, I have a mock project folder set up as follows:
pi@box:~/project $ tree
.
├── main.py
├── mod1.py
└── subfolder
├── __init__.py
├── main.py
└── mod2.py
It's a good idea to have an empty __init__.py
under subfolders, see here for more details. My main.py
looks like this:
import os
import sys
print(f'cwd = {os.getcwd()}')
print(f'path0 = {sys.path[0]}')
try:
import mod1
mod1.hello()
except Exception as e:
print(f'import mod1 failed: {e}')
try:
from subfolder import mod2
mod2.hello()
except Exception as e:
print(f'from subfolder import mod2 failed: {e}')
try:
import mod2 as mod2copy
mod2copy.hello()
except Exception as e:
print(f'import mod2copy failed: {e}')
Below are my execution results when attempting to run main.py under project
and project/subfolder
in terminal:
pi@box:~/project $ python3 main.py
cwd = /home/pi/project
path0 = /home/pi/project
Module 1 reporting in!
Module 2 reporting in!
import mod2copy failed: No module named 'mod2'
pi@box:~/project $ python3 ./subfolder/main.py
cwd = /home/pi/project
path0 = /home/pi/project/subfolder
import mod1 failed: No module named 'mod1'
from subfolder import mod2 failed: No module named 'subfolder'
Module 2 reporting in!
pi@box:~/project $ cd subfolder
pi@box:~/project/subfolder $ python3 main.py
cwd = /home/pi/project/subfolder
path0 = /home/pi/project/subfolder
import mod1 failed: No module named 'mod1'
from subfolder import mod2 failed: No module named 'subfolder'
Module 2 reporting in!
pi@box:~/project/subfolder $ python3 ../main.py
cwd = /home/pi/project/subfolder
path0 = /home/pi/project
Module 1 reporting in!
Module 2 reporting in!
import mod2copy failed: No module named 'mod2'
You can see that between cwd
and sys.path
, it is sys.path
that directly affects my import
s, which is determined by where your main.py
is stored. When running main.py
under the project root, I was able to import both mod1
from root and mod2
from subfolder as expected. mod2copy
is supposed to fail because there is no mod2
in root. However when executing main.py
stored in the subfolder, mod1
has failed to import because python doesn't know where mod1
is stored, due to missing sys.path
. If I however added this following line before import
ing:
sys.path.append('/home/pi/project')
The result of the main.py
under subfolder will become:
pi@rpirpirpi:~/project/subfolder $ python3 main.py
cwd = /home/pi/project/subfolder
path0 = /home/pi/project/subfolder
Module 1 reporting in!
Module 2 reporting in!
Module 2 reporting in!
You'll note all 3 imports are successful. Python is able to locate mod1
and /subfolder/mod2
because the root path is now added to the script's sys.path
. And mod2copy
is still successful because the subfolder
is already part of the sys.path
list before the append.
All that said, it gets messy when you have a module that references another module inside the substructure. Say, /subfolder/module3
tries to import mod2
and you're executing from /project/main.py
, the line import mod2
when your script execute from subfolder import mod3
will return a ModuleNotFoundError
just as before because sys.path
doesn't contain /project/subfolder
, so you'll need some finesse in all these import
s between modules. Another thing to consider is relative path - if you start moving files around, all these sys.path
will need to be maintained.
To summarize - if you are expecting to import modules that are neither in the Python library nor nested under your project root, you're in for a bad time.
The above was a quick and easy remedy for small ad-hoc projects, say, for temporary testing before you finalize the modules. But if your intention is to reuse these modules for future projects, consider storing them in a centralized path and add to your PYTHONPATH. This thread have some more information,, for example if you want to store your modules under /home/myname/modules
:
add the below line to your ~/.bashrc
:
export PYTHONPATH="${PYTHONPATH}:/home/myname/modules"
... and then add an empty file named __init__.py
in each folder created under modules
(including modules
itself) to avoid import issues.
If you are up for the extra work, as mentioned, you can always look into converting the modules into a package and install it via pip. This way you don't have to worry about PATH handling at all.