Python code runs from IDE, but not from terminal

痞子三分冷 提交于 2019-12-12 10:58:43

问题


My imports don't work when I try to run the code from Linux terminal. Specifically, imports from other packages in the same project. I know this is a PYTHONPATH issue, but I don't know how to diagnose it further or solve it. The code runs fine inside the IDE (eclipse).

I am interested in a permanent solution, guessing it will involve editing .bashrc. I simply want to invoke scripts from command line, like

python my_script.py

os.environ["PYTHONPATH"] gives a key error in ipython terminal.

I tried

print os.getcwd()
print sys.path

Inside IDE

/home/myname/workspace/project2/main

['/home/myname/workspace/project2/main', '/home/myname/workspacep/problem2', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_6
4-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/p
ython2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PILcompat', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/pytho
n2.7/dist-packages/ubuntu-sso-client', '/usr/lib/pymodules/python2.7', '/usr/lib/python2.7/lib-old']

Inside terminal

/home/myname/workspace/project2/main

['/home/myname/workspace/project2/main', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PILcompat', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/python2.7/dist-packages/ubuntu-sso-client']

回答1:


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.paths will change in terminal depending on where you run it from and where the file resides. But the key is sys.paths 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 imports, 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 importing:

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 imports 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.




回答2:


The difference between executing your script in Pycharm Eclipse vs a bash shell is the value of the environment variable $PYTHONPATH.

In Pycharm, go to preferences, then project interpreter settings and hover over the package that you're not finding in terminal. The path where that package is located should present itself. Eclipse, figure out where your project's environment variables are stored, or find the path of the modules in question.

Add that path to $PYTHONPATH in your shell with

PYTHONPATH=$PYTHONPATH:your/path/here

You can add that line to your .bashrc or .bash_profile file, you can add it to your bash script, or you can just type it every time.

Update in response to OP comment:

Use the path that points to the directory where the python modules you’re not locating are installed.

Try

python -v

in your IDE console. That should give you a list of modules and their directories.

Use the same command in your shell and the differences will show you what is missing where.



来源:https://stackoverflow.com/questions/48532134/python-code-runs-from-ide-but-not-from-terminal

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!