当我尝试从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']
答案 0 :(得分:1)
我的问题是我正在使用的python文件的名称,它与我正在导入的包同名并做了一个循环
答案 1 :(得分:0)
在 Pycharm Eclipse中执行脚本与bash shell之间的区别是环境变量$ PYTHONPATH的值。
在 Pycharm中,转到首选项,然后设置解释器设置并将鼠标悬停在您未在终端中找到的包中。该软件包所在的路径应该出现。 Eclipse,找出存储项目环境变量的位置,或找到相关模块的路径。
使用
将该路径添加到shell中的$ PYTHONPATHPYTHONPATH=$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}')
尝试在终端中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
之间的sys.path
直接影响我的import
,这取决于main.py
的位置存储。在项目根目录下运行main.py
时,我能够按预期从子文件夹和mod1
导入mod2
。 mod2copy
应该失败,因为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安装所有导入的库。