导入语句在 PyCharm 上可以运行,但在终端上无法运行。

54

PyCharm 2016.2.3,Mac OS X 10.11.1,Python 3.5(Homebrew);

我有这个文件夹结构

project
  /somepackage
    /subpackage
     __init__.py   
     bar.py
   __init__.py
   foo.py

foo.py:

import somepackage.subpackage.bar
print("foo")

bar.py:

print("bar")

所以我期望的输出是

bar
foo

在PyCharm中运行正常,但是从终端运行时出现了ImportError错误:

$ pwd
$ /home/project (not the actual path; just omitting some personal stuff)
$ python3.5 somepackage/foo.py
File "foo.py", line 1, in <module>
import somepackage.subpackage.bar
ImportError: No module named 'somepackage'

我找到了这个问题,它与我的问题相同。然而,建议的解决方案并没有对我起作用,因为我确实使用的是与PyCharm相同的Python解释器,并且我当前位于包含/somepackage文件夹的目录中。

有人有其他关于如何解决这个问题的建议吗?

4个回答

62

您正在像运行脚本一样运行foo.py文件,但实际上您是在将其作为模块使用。因此,正确的解决方案是将其作为模块运行:

python3 -m somepackage.foo

顺便提一下,另一个选择是编辑您的路径,如下:

export PYTHONPATH=.

(或者你可以在那里放置绝对目录,当然你应该追加任何已经在PYTHONPATH中的其他目录。)这更接近于PyCharm的做法,但在哲学上不正确。


3
在“命令行和环境文档”中有提到这个内容,但如果你不知道解决方案,就不太容易去寻找。很遗憾在“教程模块”甚至是高度技术的“导入系统参考文档”中都没有提到它。 - Arthur Tacca
@ArthurTacca 是的,确实:当使用 -m 模块名 调用时,给定的模块在 Python 模块路径上被找到并作为脚本执行。希望我能给这个点赞两次 ;) - alex
@Kaushal28 根据我在回答中提到的“记录另一种选择”的部分,编辑您的 PYTHONPATH - Arthur Tacca
export PYTHONPATH=. 是什么意思? - Rylan Schaeffer
@RylanSchaeffer 首先是一些背景:默认情况下,导入语句会在包含你在命令行中传递的 Python 文件的目录中查找。例如:如果你 cd mydir 然后运行 python foo/bar.py(所以 mydir 包含一个子目录 foo,其中包含一个文件 bar.py),那么默认情况下 import mymodule 将在 foo 子目录中查找 mymodule.py。但是 export PYTHONPATH=. 告诉 Python 也要在当前目录中查找。在这个例子中,它还会在 mydir 中查找 mymodule.py - Arthur Tacca
显示剩余3条评论

8

如上所述,设置PYTHONPATH是使其工作的关键。 我使用以下VSCODE .env内容,以便它适用于任何项目:

PYTHONPATH=${PROJ_DIR}:${PYTHONPATH}

当你在运行/调试配置中勾选“将内容根目录添加到PYTHONPATH”时,PyCharm基本上执行的就是这个操作。这是一个非常有用的设置,但会让你变得依赖于PyCharm,因为你的代码在PyCharm之外运行时会失败。

或者,如果你在终端中运行,请首先导出:

export PYTHONPATH=...

我花了好几天时间才弄明白这些。


6

我通过以下两个步骤在Linux上解决了我的问题:

  1. 第一步 进入您的项目根目录并设置:
export PYTHONPATH=$PATHONPATH:`pwd`
  1. 第二步 运行 python3 -m somepackage.foo 请注意不要加 '.py' 后缀

0

我刚刚使用scapy.layers.http模块遇到了同样的问题,这个问题出现在我的Kali(linux-Debian)上,但在Win-10上运行良好(经过一些修改后)。

包已正确安装(scapy-http),程序在PyCharm中运行正常,但在终端作为脚本运行时却不行。

我尝试通过重新在主根目录中安装以及更改sys.path来解决它,但都没有起作用。

故障排除和解决方案

  1. 我发现它在以下位置查找http模块:

    /usr/local/lib/python3.7/dist-packages/scapy/layers/init.py

并且得到了ImportError:

from scapy.layers import http --->
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: cannot import name 'http' from 'scapy.layers' (/usr/local/lib/python3.7/dist-packages/scapy/layers/__init__.py)

然后我检查了实际安装的scapy-http位置,即称为http.py的模块,因此我将其复制到:
/usr/local/lib/python3.7/dist-packages/scapy/layers/  

在/usr/local/lib/python3.7/dist-packages/scapy_http/找到了http.py文件

搞定了 :)!

我知道有点小问题,但是它起作用了!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接