![](/img/trans.png)
[英]VS code runs python with no errors only if started from conda terminal
[英]Python code runs from IDE, but not from terminal
当我尝试从 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']
我的问题是我正在使用的 python 文件的名称,它与我正在导入的包同名并做了一个循环
在Pycharm Eclipse 中执行脚本与在 bash shell 中执行脚本之间的区别在于环境变量 $PYTHONPATH 的值。
在Pycharm 中,转到首选项,然后项目解释器设置并将鼠标悬停在您在终端中找不到的包上。 该包所在的路径应该显示出来。 Eclipse,找出你项目的环境变量的存储位置,或者找到有问题的模块的路径。
将该路径添加到 shell 中的 $PYTHONPATH 中
PYTHONPATH=$PYTHONPATH:your/path/here
您可以将该行添加到您的 .bashrc 或 .bash_profile 文件中,您可以将其添加到您的 bash 脚本中,或者您可以每次都输入它。
更新响应 OP 评论:
使用指向安装了您未找到的 python 模块的目录的路径。
试试
python -v
在您的 IDE 控制台中。 这应该会给你一个模块列表和它们的目录。
在你的 shell 中使用相同的命令,差异会告诉你哪里缺少什么。
如前所述,为了说明 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
s将在终端中更改,具体取决于您从何处运行它以及文件所在的位置。 但关键是sys.path
s,因为它们告诉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
在子文件夹下有一个空的__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}')
以下是我尝试在终端中的project
和project/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'
可以看到,在cwd
和sys.path
之间,直接影响我的import
的是sys.path
,这取决于您的main.py
的存储位置。 在项目根目录下运行main.py
,我能够按预期从根目录导入mod1
和从子文件夹导入mod2
。 mod2copy
应该会失败,因为 root 中没有mod2
。 然而,当执行main.py
存储在子文件夹, mod1
未能导入,因为蟒蛇不知道去哪里mod1
存储,由于缺少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
执行,当您的脚本from subfolder import mod3
执行时,行import mod2
将像以前一样返回ModuleNotFoundError
因为sys.path
不包含/project/subfolder
,因此您需要在模块之间的所有这些import
一些技巧。 另一件要考虑的事情是相对路径——如果你开始移动文件,所有这些sys.path
都需要维护。
总而言之 - 如果您希望导入既不在 Python 库中也不嵌套在项目根目录下的模块,那么您将陷入困境。
对于小型临时项目,例如在完成模块之前进行临时测试,上述方法是一种快速而简单的补救措施。 但是,如果您打算在未来的项目中重用这些模块,请考虑将它们存储在一个集中的路径中并添加到您的 PYTHONPATH。 此线程有更多信息,例如,如果您想将模块存储在/home/myname/modules
:
~/.bashrc
下行添加到您的~/.bashrc
:export PYTHONPATH="${PYTHONPATH}:/home/myname/modules"
...然后在
modules
(包括modules
本身)下创建的每个文件夹中添加一个名为__init__.py
的空文件以避免导入问题。
如果您愿意做额外的工作,如上所述,您可以随时考虑将模块转换为包并通过 pip 安装它。 这样你就不必担心 PATH 处理了。
终端执行和 IDE 执行之间存在差异的原因可能是虚拟环境可能是为 IDE 配置的,但不是为终端运行代码的实际环境。 您可以通过运行以下命令来检查它:path_of_virt_env your_command。 'path_of_virt_env' 是运行代码表单 IDE 时 IDE 在控制台上显示为输出的第一个参数。 现在,要解决它,请在终端中 pip 安装所有导入的库。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.