Python代码从IDE运行,但不从终端运行

时间:2018-01-30 23:28:21

标签: python python-import pythonpath

当我尝试从Linux终端运行代码时,我的导入功能无法正常工作。具体来说,从同一项目中的其他包导入。我知道这是一个PYTHONPATH问题,但我不知道如何进一步诊断或解决它。 代码在IDE(eclipse)中运行良好。

我对永久解决方案感兴趣,猜测它将涉及编辑.bashrc。我只想从命令行调用脚本,比如

python my_script.py

os.environ["PYTHONPATH"]在ipython终端中给出了一个关键错误。

我试过

print os.getcwd()
print sys.path

内部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']

内部终端

/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']

4 个答案:

答案 0 :(得分:1)

我的问题是我正在使用的python文件的名称,它与我正在导入的包同名并做了一个循环

答案 1 :(得分:0)

Pycharm Eclipse中执行脚本与bash shell之间的区别是环境变量$ PYTHONPATH的值。

Pycharm中,转到首选项,然后设置解释器设置并将鼠标悬停在您未在终端中找到的包中。该软件包所在的路径应该出现。 Eclipse,找出存储项目环境变量的位置,或找到相关模块的路径。

使用

将该路径添加到shell中的$ PYTHONPATH
PYTHONPATH=$PYTHONPATH:your/path/here

您可以将该行添加到.bashrc或.bash_profile文件中,您可以将其添加到bash脚本中,也可以每次都输入。

响应OP评论更新:

使用指向未安装python模块的目录的路径。

尝试

python -v
在IDE控制台中

。这应该会给你一个模块及其目录列表。

在shell中使用相同的命令,差异将显示缺少的位置。

答案 2 :(得分:0)

如上所述,为了说明IDE执行和终端执行期间使用的路径的不同,请在IDE和终端中运行以下脚本:

import os
import sys
print(os.getcwd())
for i in sys.path:
    print(i)

比较您的结果,从终端执行时,与在IDE中运行相比,这些文件夹丢失了:

'/home/myname/workspacep/problem2' 
'/usr/lib/pymodules/python2.7'

需要注意的是,当前工作目录和sys.path 在终端中更改,具体取决于您从哪里运行以及文件所在的位置。但关键是sys.path,因为它们告诉python在哪里寻找模块。

我愿意打赌您尝试导入的模块来自其中一个文件夹,很可能是在/home/myname/workspacep/problem2下。这会引入问题,因为您的模块既不存储在集中访问位置(例如,/usr/lib/python2.7/my_modules),也不存储在项目结构下的子文件夹中。

为了说明,我有一个模拟项目文件夹设置如下:

pi@box:~/project $ tree
.
├── main.py
├── mod1.py
└── subfolder
    ├── __init__.py
    ├── main.py
    └── mod2.py

在子文件夹see here for more details下放置__init__.py是个好主意。我的main.py看起来像这样:

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}')

尝试在终端中projectproject/subfolder下运行main.py时,我的执行结果如下:

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'

您可以看到cwdsys.path之间的sys.path直接影响我的import,这取决于main.py的位置存储。在项目根目录下运行main.py时,我能够按预期从子文件夹和mod1导入mod2mod2copy应该失败,因为root中没有mod2。但是,当执行存储在子文件夹中的main.py时,mod1无法导入,因为由于缺少mod1,python无法知道sys.path的存储位置。但是,如果我在import之前添加了以下这一行:

sys.path.append('/home/pi/project')

子文件夹下main.py的结果将变为:

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!

您会注意到所有3个导入都是成功的。 Python能够找到mod1/subfolder/mod2,因为根路径现在已添加到脚本sys.path中。并且mod2copy仍然成功,因为subfolder已经是追加之前sys.path列表的一部分。

所有这一切,当你有一个模块引用子结构中的另一个模块时,它会变得混乱。说,/subfolder/module3尝试import mod2并且您从/project/main.py开始执行,当您的脚本执行import mod2时,from subfolder import mod3行将返回{{1}就像以前一样因为ModuleNotFoundError不包含sys.path,所以你需要在模块之间的所有这些/project/subfolder中使用一些技巧。另一件需要考虑的事情是相对路径 - 如果您开始移动文件,则需要维护所有这些import

总结一下 - 如果您希望导入既不在Python库中也不嵌套在项目根目录下的模块,那么您将陷入困境。

以上是针对小型临时项目的快速简便的补救措施,例如,在最终确定模块之前进行临时测试。但是,如果您打算在将来的项目中重用这些模块,请考虑将它们存储在集中路径中并添加到PYTHONPATH中。 This thread have some more information,,例如,如果您想将模块存储在sys.path

  

将以下行添加到/home/myname/modules

~/.bashrc
     

...然后在export PYTHONPATH="${PYTHONPATH}:/home/myname/modules" 下创建的每个文件夹中添加一个名为__init__.py的空文件(包括modules本身)以避免导入问题。

如果您需要额外的工作,如上所述,您可以随时查看将模块转换为包并通过pip安装。这样你根本不必担心PATH处理。

答案 3 :(得分:0)

从终端和从IDE执行之间差异的原因可能是为IDE配置的虚拟环境,而不是由终端运行代码的实际环境。 您可以通过运行以下命令进行检查:path_of_virt_env your_command。 当运行代码形式的IDE时,“ path_of_virt_env”是您的IDE在控制台上显示为控制台输出的第一个参数。 现在,要解决此问题,请在终端中pip安装所有导入的库。