PyLint“无法导入”错误 - 如何设置PYTHONPATH?

325

我正在Windows上从Wing IDE内部运行PyLint。我的项目中有一个子目录(包),在该包内部,我从顶层导入了一个模块。

__init__.py
myapp.py
one.py
subdir\
    __init__.py
    two.py

我在two.py文件中使用import one导入模块,在运行时可以正常工作,因为顶层目录(从中运行myapp.py)已经在Python路径中。然而,当我在two.py上运行PyLint时,它会给出一个错误:

F0401: Unable to import 'one'

我该如何修复这个问题?

34个回答

256

我知道有两个选项。

第一种是更改 PYTHONPATH 环境变量以包含您的模块上层目录。

或者,您还可以编辑 ~/.pylintrc 文件以包含您的模块上层目录,方法如下:

[MASTER]
init-hook='import sys; sys.path.append("/path/to/root")'

(或者在pylint的其他版本中,init-hook要求您将[General]更改为[MASTER])

这两个选项都应该有效。


19
这个pylint钩子目前是在VScode中使用的最佳方式,因为PYTHONPATH尚未支持其内置的linter使用。 - Danny Staple
3
我遇到了使用 MacVim 和 syntastic 时相同的问题。我该如何配置 prosector 来解决导入错误? - Laurent
2
相关博客文章,包含更多细节。点击此处阅读 - Christian Long
1
“~/.pylintrc” 在我的OSX上起作用了,另一个没有起作用。 - Miquel
1
我们不能使用 python -m pylint 标志来解决这个问题吗? - variable
显示剩余10条评论

135

init-hook中更改路径的解决方案很好,但我不喜欢必须在那里添加绝对路径的事实,因此我无法将这个pylintrc文件与项目的其他开发人员共享。对我来说,使用相对路径到pylintrc文件的这个解决方案更好:

[MASTER]
init-hook="from pylint.config import find_pylintrc; import os, sys; sys.path.append(os.path.dirname(find_pylintrc()))"
请注意,pylint.config.PYLINTRC也存在,并且与find_pylintrc()具有相同的值。

2
确认这确实为 E0611 和 E0401 pylint 错误提供了解决方案。对于 VSCode 用户:重要的是打开的文件夹是“Python 根文件夹”,并且 .pylintrc 文件位于该文件夹中。 - Niko Pasanen
同样,确保您的模块目录名称不要以 .(点)开头。 - Saw-mon and Natalie
9
如果您想要添加一个特定的子文件夹(例如app),您可以使用以下代码:from pylint.config import find_pylintrc; import os, sys; sys.path.append(os.path.join(os.path.dirname(find_pylintrc()), 'app')) - chachan
在我的设置中,相关的包位于项目根目录之外,因此我的代码行如下: init-hook="from pylint.config import find_pylintrc; import os, sys; sys.path.append(os.path.join(os.path.dirname(find_pylintrc()),".."))" - guo
这个完美运行,即使在Jenkins CI期间也是如此。 - MNA
4
如果您正在使用 pyproject.toml 文件,这段代码将无法正常工作,请改用以下代码:from pylint.config import find_default_config_files; import os, sys; sys.path.append(os.path.dirname(next(find_default_config_files()))) - Cesar Canassa

75
问题可以通过在 venv 下配置 pylint 路径来解决: $ cat .vscode/settings.json
{
    "python.pythonPath": "venv/bin/python",
    "python.linting.pylintPath": "venv/bin/pylint"
}

7
对于Windows系统而言,`{ "python.pythonPath": "${workspaceFolder}\.venv\Scripts\python.exe""python.linting.pylintPath": "${workspaceFolder}\\.venv\\Scripts\\pylint.exe"} `仅供完整性参考。 - Roy2511
4
现在,VSCode 显示以下信息: The setting "python.pythonPath" defined in your settings.json is now deprecated.如果我删除 python.pythonPath 行,它似乎仍然可以工作。 - Jesse Aldridge
3
这比更改导入路径要简单得多。对于任何使用 poetry(默认情况下在 .venv/ 中创建其虚拟环境)的人来说,这非常完美: "python.linting.pylintPath": "${workspaceFolder}/.venv/bin/pylint", - cglacet
3
在我的情况下,只需添加 "python.linting.pylintPath": "venv/bin/pylint" 就足够了,尽管我已经设置了 pythonPath。 - Gustavo Barros
3
这似乎与 OP 无关。它没有提到 vscode 特定实现的任何内容。 - jobu1342
显示剩余2条评论

48

创建.pylintrc文件并添加。

[MASTER]
init-hook="from pylint.config import find_pylintrc;
import os, sys; sys.path.append(os.path.dirname(find_pylintrc()))"

40
这个链接名称让我感到困惑。 - Keverly
2
我想补充一点,这个文件应该放在你想要添加到PYTHONPATH的目录中。此外,只有当双引号命令在单行上而不是两行时,这才对我有效,就像上面那样。 - huyz

41

你是否在两个目录中都有一个空的__init__.py文件,以便让Python知道这些目录是模块?

当你不是从文件夹内运行(例如,可能是从pylint运行),基本的大纲如下:

topdir\
  __init__.py
  functions_etc.py
  subdir\
    __init__.py
    other_functions.py
这是Python解释器如何在没有引用当前目录的情况下了解模块的方式,因此如果pylint从自己的绝对路径运行,它就能够访问functions_etc.py,并将其识别为topdir.functions_etctopdir.subdir.other_functions,前提是topdirPYTHONPATH上。
更新:如果问题不是__init__.py文件,则可以尝试将模块复制或移动到c:\Python26\Lib\site-packages - 这是一个常见的放置附加包的地方,并且肯定会在pythonpath上。如果您知道如何执行Windows符号链接或等效操作(我不知道!),则可以使用该方法。这里有很多更多的选项(http://docs.python.org/install/index.html),包括将sys.path附加到开发代码的用户级目录中,但是在实践中,我通常只是将我的本地开发目录符号链接到site-packages-将其复制过去具有相同的效果。

3
是的,我两个目录中都有__init__.py文件。我认为问题在于当 PyLint 运行时顶层目录不在 PYTHONPATH 中,我不确定如何解决这个问题。 - EMP
符号链接是个好主意,但只有从 Windows Vista 开始支持,而我正在使用 XP。我想我可以尝试硬链接它... - EMP
硬链接:不,最好不要这样做。我曾经尝试过,虽然它确实可以工作(在某种程度上),但它不会按照你的期望工作。 - shylent
2
符号链接不是一个好主意。这只会在您的机器上解决问题 - 当其他人检出项目时,它们将无法正常工作。 - Jonathan Hartley

40

我在项目的根目录下添加了一个名为pylintrc的新文件。

[MASTER]
init-hook='import sys; sys.path.append(".")'

它对我在PyCharm IDE中可行。


在我的VS Code中也可以工作。谢谢! - Wesley Cheek
2
这是唯一在我的电脑上有效的答案。我尝试了上面的其他答案,但都不起作用。 - Muhammad Dyas Yaskur
在我的VSCode上运行良好,谢谢…顺便提一下:为了刷新缓存,还需要重新启动VSCode。 - Max Alexander Hanna
运行得非常好;请注意,您可以使用 pylintrc.pylintrc 中的任何一个。 - isCzech
同样的问题,只有这个解决方案适用于我。谢谢! - sailfish009

32

1) sys.path是一个列表。

2) 问题在于,有时sys.path不是你的虚拟环境路径,而你想在虚拟环境中使用pylint。

3) 因此,像上面所说,使用init-hook(注意在'和"中解析pylint是严格的)。

[Master]
init-hook='sys.path = ["/path/myapps/bin/", "/path/to/myapps/lib/python3.3/site-packages/", ... many paths here])'

或者

[Master]
init-hook='sys.path = list(); sys.path.append("/path/to/foo")'

.. and

pylint --rcfile /path/to/pylintrc /path/to/module.py

9

我不知道WingIDE如何使用,但是对于在Geany中使用PyLint,我将我的外部命令设置为:

PYTHONPATH=${PYTHONPATH}:$(dirname %d) pylint --output-format=parseable --reports=n "%f"

%f 是文件名,%d 是路径。这可能对某些人有用 :)


5

我必须更新系统的PYTHONPATH变量,以添加我的App Engine路径。在我的情况下,我只需要编辑我的~/.bashrc文件并添加以下行:

export PYTHONPATH=$PYTHONPATH:/path/to/google_appengine_folder

事实上,我先尝试设置init-hook,但这并没有一致地解决我的代码库中的问题(不知道为什么)。一旦将其添加到系统路径中(总的来说可能是个好主意),我的问题就解决了。


4

尝试

if __name__ == '__main__':
    from [whatever the name of your package is] import one
else:
    import one

请注意,在Python 3中,else子句的语法如下:
from .. import one

重新考虑后,这可能无法解决您特定的问题。我误解了问题,并认为two.py是作为主模块运行的,但事实并非如此。并且考虑到Python 2.6(没有从__future__中导入absolute_import)和Python 3.x处理导入的方式的差异,您在Python 2.6中不需要这样做,我认为。

不过,如果您最终切换到Python 3并计划将一个模块同时用作包模块和包内独立脚本,则保留类似以下内容可能是个好主意:

if __name__ == '__main__':
    from [whatever the name of your package is] import one   # assuming the package is in the current working directory or a subdirectory of PYTHONPATH
else:
    from .. import one

想法。

编辑:现在为您提供可能解决您实际问题的方法。从包含您的one模块的目录中运行PyLint(通过命令行,也许),或者在运行PyLint时将以下代码放在某个地方:

import os

olddir = os.getcwd()
os.chdir([path_of_directory_containing_module_one])
import one
os.chdir(olddir)

基本上,与其操纵PYTHONPATH,只需确保当前工作目录是包含one.py的目录,然后进行导入。

(看看Brian的答案,你可能会将前面的代码分配给init_hook,但如果你要这样做,那么你可以简单地执行他所做的向sys.path追加操作,这比我的解决方案略微更优雅。)


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