【问题标题】:PyLint "Unable to import" error - how to set PYTHONPATH?PyLint“无法导入”错误 - 如何设置 PYTHONPATH?
【发布时间】:2010-12-26 08:18:51
【问题描述】:

我在 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'

我该如何解决这个问题?

【问题讨论】:

    标签: python virtualenv pylint pythonpath


    【解决方案1】:

    我知道有两种选择。

    一,更改PYTHONPATH 环境变量以包含您的模块上方的目录。

    或者,编辑~/.pylintrc 以包含模块上方的目录,如下所示:

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

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

    这两个选项都应该有效。

    希望对您有所帮助。

    【讨论】:

    • 这个 pylint 钩子目前是 VScode 中最好的方法,因为 PYTHONPATH 尚不支持,因为它内置在 linter 使用中。
    • 我在使用带有 syntastic 的 MacVim 时遇到了同样的问题。如何配置 prosector 以修复导入错误?
    • Related blog post 提供更多详细信息。
    • ~/.pylintrc 在 OSX 上为我工作,另一个没有工作
    • 不知道为什么这不是公认的答案 - 另外,对于那些绊脚的人来说,值得一提的是,您需要 export PYTHONPATH 以便 pylint 看到它(至少,在 bash/ zsh)
    【解决方案2】:

    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() 具有相同的值。

    【讨论】:

    • 确认这确实为 E0611 和 E0401 pylint 错误提供了解决方案。对于 VSCode 用户:重要的是打开的文件夹是“python 根文件夹”,并且 .pylintrc 位于该文件夹中。
    • 另外,请确保您的模块目录名称都不以.(点)开头。
    • 如果你想添加一个特定的子文件夹(即app)你可以使用from pylint.config import find_pylintrc; import os, sys; sys.path.append(os.path.join(os.path.dirname(find_pylintrc()), 'app'))
    • 在我的设置中,有问题的包位于项目的根目录之外,因此我的行如下所示:init-hook="from pylint.config import find_pylintrc; import os, sys; sys.path.append(os.path.join(os.path.dirname(find_pylintrc()),".."))"
    • 即使在 Jenkins CI 期间也能完美运行
    【解决方案3】:

    问题可以通过在venv下配置pylint路径来解决: $ cat .vscode/settings.json

    {
        "python.pythonPath": "venv/bin/python",
        "python.linting.pylintPath": "venv/bin/pylint"
    }
    

    【讨论】:

    • 对于 Windows,它是 { "python.pythonPath": "${workspaceFolder}\\.venv\\Scripts\\python.exe" "python.linting.pylintPath": "${workspaceFolder}\\.venv\\Scripts\\pylint.exe" } 只是为了完整性。
    • VSCode 现在显示此消息:The setting "python.pythonPath" defined in your settings.json is now deprecated. 如果我删除 python.pythonPath 行,它似乎仍然有效。
    • 就这么简单。这听起来比更改导入路径要好得多。这对于使用poetry(默认在.venv/ 创建其虚拟环境)的任何人都非常有效:"python.linting.pylintPath": "${workspaceFolder}/.venv/bin/pylint",
    • 添加 "python.linting.pylintPath": "venv/bin/pylint" 对我来说已经足够了,虽然我已经设置了 pythonPath
    • 这看起来与 OP 无关。它没有说明特定于 vscode 的实现。
    【解决方案4】:

    你是否在两个目录中都有一个空的__init__.py 文件让 python 知道目录是模块?

    当您不在文件夹内运行时(即可能来自 pylint,虽然我没有使用过),基本大纲是:

    topdir\
      __init__.py
      functions_etc.py
      subdir\
        __init__.py
        other_functions.py
    

    这就是python解释器在不参考当前目录的情况下知道模块的方式,所以如果pylint从它自己的绝对路径运行,它将能够以topdir.functions_etctopdir.subdir.other_functions访问functions_etc.py,前提是topdirPYTHONPATH 上。

    更新:如果问题不是__init__.py 文件,也许只是尝试将您的模块复制或移动到c:\Python26\Lib\site-packages - 这是放置附加包的常见位置,并且肯定会在您的pythonpath 上。如果您知道如何执行 Windows 符号链接或等效的操作(我不知道!),您可以这样做。还有更多选项here: http://docs.python.org/install/index.html,包括将 sys.path 附加到开发代码的用户级目录的选项,但实际上我通常只是象征性地将我的本地开发目录链接到站点包 - 将其复制过来有效果一样。

    【讨论】:

    • 是的,我在两个目录中都有__init__.py。我认为问题在于 PyLint 运行时顶部目录不在 PYTHONPATH 中,我不知道如何解决。
    • 符号链接是个好主意,但它只支持从 Windows Vista 开始,而且我正在运行 XP。我想我可以尝试硬链接它...
    • 重新硬链接:不,你最好不要这样做。我玩过它,虽然它确实有效(在某种程度上),但它不会像你期望的那样有效。
    • 符号链接不是一个好主意。这只能解决您机器上的问题 - 当其他人签出项目时,它会被他们破坏。
    【解决方案5】:

    我在此页面上找到的这个问题的一般答案PLEASE NOT OPEN, SITE IS BUGED

    创建.pylintrc 并添加

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

    【讨论】:

    • 这个链接名让我很困惑
    【解决方案6】:

    1) sys.path 是一个列表。

    2) 问题有时是 sys.path 不是您的 virtualenv.path,而您想在 virtualenv 中使用 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")'
    

    .. 和

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

    【讨论】:

      【解决方案7】:

      我在项目的根目录中添加了一个新文件pylintrc

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

      它在 PyCharm IDE 中对我有用

      【讨论】:

        【解决方案8】:

        我不知道它如何与 WingIDE 一起工作,但为了将 PyLint 与 Geany 一起使用,我将外部命令设置为:

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

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

        【讨论】:

          【解决方案9】:

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

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

          事实上,我首先尝试设置init-hook,但这并没有在我的代码库中始终如一地解决问题(不知道为什么)。一旦我将它添加到系统路径(通常可能是一个好主意),我的问题就消失了。

          【讨论】:

            【解决方案10】:

            我刚刚发现的一个解决方法是实际上只为整个包而不是单个文件运行 PyLint。不知何故,它设法找到导入的模块。

            【讨论】:

            • 听起来不错;怎么样?
            • @CeesTimmerman 从父文件夹运行pylint ... dir。这要求__init__.py 出现在每个带有.py 文件的子文件夹中。
            【解决方案11】:

            试试

            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,这稍微更优雅比我的解决方案。)

            【讨论】:

              【解决方案12】:

              我遇到了同样的问题,并通过在我的 virtualenv 中安装 pylint 然后将 .pylintrc 文件添加到我的项目目录中并在文件中添加以下内容来解决它:

              [Master]
              init-hook='sys.path = list(); sys.path.append("./Lib/site-packages/")'
              

              【讨论】:

              • 我必须确认这消除了 E0611 pylint 错误,但 E0401 错误仍然存​​在。
              【解决方案13】:

              我找到了一个不错的answer。编辑您的 pylintrc 并在 master 中添加以下内容

              init-hook="import imp, os; from pylint.config import find_pylintrc; imp.load_source('import_hook', os.path.join(os.path.dirname(find_pylintrc()), 'import_hook.py'))"
              

              【讨论】:

                【解决方案14】:

                安装 Python 时,可以设置路径。如果路径已经定义,那么您可以在 VS Code 中执行操作,按 Ctrl+Shift+P 并键入 Python:选择解释器并选择 Python 的更新版本。点击此链接了解更多信息,https://code.visualstudio.com/docs/python/environments

                【讨论】:

                  【解决方案15】:

                  如果您想从交给pylint 的当前模块/文件向上查找模块的根目录,这将完成。

                  [MASTER]
                  init-hook=sys.path += [os.path.abspath(os.path.join(os.path.sep, *sys.argv[-1].split(os.sep)[:i])) for i, _ in enumerate(sys.argv[-1].split(os.sep)) if os.path.isdir(os.path.abspath(os.path.join(os.path.sep, *sys.argv[-1].split(os.sep)[:i], '.git')))][::-1]
                  

                  如果你有一个 python 模块~/code/mymodule/,具有这样的顶级目录布局

                  ~/code/mymodule/
                  ├── .pylintrc
                  ├── mymodule/
                  │   └── src.py
                  └── tests/
                      └── test_src.py
                  

                  然后这会将~/code/mymodule/ 添加到您的python 路径并允许pylint 在您的IDE 中运行,即使您在tests/test_src.py 中导入mymodule.src

                  您可以将检查换成 .pylintrc,但是当涉及到 python 模块的根目录时,通常需要一个 git 目录。

                  在你问之前

                  使用import sys, os; sys.path.append(...) 的答案缺少可以证明我的答案格式合理的内容。我通常不会那样编写代码,但在这种情况下,您会遇到 pylintrc 配置解析器和评估器的限制。它实际上在the context of the init_hook callback 中运行exec,因此任何导入pathlib、使用多行语句、将某些内容存储到变量等的尝试都将无效。

                  我的代码的一种不那么恶心的形式可能如下所示:

                  import os
                  import sys
                  
                  def look_for_git_dirs(filename):
                      has_git_dir = []
                      filename_parts = filename.split(os.sep)
                      for i, _ in enumerate(filename_parts):
                          filename_part = os.path.abspath(os.path.join(os.path.sep, *filename_parts[:i]))
                          if os.path.isdir(os.path.join(filename_part, '.git')):
                              has_git_dir.append(filename_part)
                      return has_git_dir[::-1]
                  
                  # don't use .append() in case there's < 1 or > 1 matches found
                  sys.path += look_for_git_dirs(sys.argv[-1])
                  

                  我希望我可以使用pathlib.Path(filename).parents,它会让事情变得更容易。

                  【讨论】:

                  • 虽然没有真正建议,但可以使用__import__ 函数导入,这里可能很方便
                  【解决方案16】:

                  我有同样的问题,因为我找不到答案,我希望这可以帮助任何有类似问题的人。

                  我将flymake与epylint一起使用。基本上我所做的是添加一个 dired-mode-hook 来检查 dired 目录是否是 python 包目录。如果是,我将它添加到 PYTHONPATH。在我的例子中,如果一个目录包含一个名为“setup.py”的文件,我认为它是一个 python 包。

                  ;;;;;;;;;;;;;;;;;
                  ;; PYTHON PATH ;;
                  ;;;;;;;;;;;;;;;;;
                  
                  (defun python-expand-path ()
                    "Append a directory to the PYTHONPATH."
                    (interactive
                     (let ((string (read-directory-name 
                            "Python package directory: " 
                            nil 
                            'my-history)))
                       (setenv "PYTHONPATH" (concat (expand-file-name string)
                                    (getenv ":PYTHONPATH"))))))
                  
                  (defun pythonpath-dired-mode-hook ()
                    (let ((setup_py (concat default-directory "setup.py"))
                      (directory (expand-file-name default-directory)))
                      ;;   (if (file-exists-p setup_py)
                      (if (is-python-package-directory directory)
                      (let ((pythonpath (concat (getenv "PYTHONPATH") ":" 
                                    (expand-file-name directory))))
                        (setenv "PYTHONPATH" pythonpath)
                        (message (concat "PYTHONPATH=" (getenv "PYTHONPATH")))))))
                  
                  (defun is-python-package-directory (directory)
                    (let ((setup_py (concat directory "setup.py")))
                      (file-exists-p setup_py)))
                  
                  (add-hook 'dired-mode-hook 'pythonpath-dired-mode-hook)
                  

                  希望这会有所帮助。

                  【讨论】:

                    【解决方案17】:

                    关键是将你的项目目录添加到sys.path,而不考虑环境变量。

                    对于使用 VSCode 的人,如果您的项目有一个基本目录,这里有一个适合您的单行解决方案:

                    [MASTER]
                    init-hook='base_dir="my_spider"; import sys,os,re; _re=re.search(r".+\/" + base_dir, os.getcwd()); project_dir = _re.group() if _re else os.path.join(os.getcwd(), base_dir); sys.path.append(project_dir)'
                    

                    让我稍微解释一下:

                    • re.search(r".+\/" + base_dir, os.getcwd()).group():根据编辑文件找到基目录

                    • os.path.join(os.getcwd(), base_dir):将cwd添加到sys.path以满足命令行环境


                    仅供参考,这是我的 .pylintrc:

                    https://gist.github.com/chuyik/f0ffc41a6948b6c87c7160151ffe8c2f

                    【讨论】:

                      【解决方案18】:

                      首先,转到您的 VS Code,然后按“ctrl + shift + p”

                      然后搜索settings.json

                      然后将下面的代码粘贴到settings.jason中。希望问题能解决。

                      {

                      "python.pythonPath": "venv/bin/python",
                      "python.linting.pylintPath": "venv/bin/pylint"
                      

                      }

                      【讨论】:

                        【解决方案19】:

                        也许通过手动将目录附加到 PYTHONPATH 中?

                        sys.path.append(dirname)
                        

                        【讨论】:

                        • 嗯,但是你会把那个代码放在哪里呢?在每个文件的顶部?我想它会起作用,但只是让 PyLint 工作是相当困难的。
                        • @Evgeny:查看 Brian M. Hunt 最近发布的答案。
                        • 由于某种原因,在每个文件的顶部添加它不起作用 - PyLint 似乎完全满足于忽略它正在扫描的模块内对 sys.path 所做的任何修改。不过,我并没有费心去研究原因……
                        【解决方案20】:

                        如果有人正在寻找一种方法来将 pylint 作为 PyCharm 中的外部工具运行并让它在他们的虚拟环境中工作(为什么我来这个问题),我是这样解决的:

                        1. 在 PyCharm > 首选项 > 工具 > 外部工具中,为 pylint 添加或编辑项目。
                        2. 在编辑工具对话框的工具设置中,将程序设置为使用 python 解释器目录中的 pylint:$PyInterpreterDirectory$/pylint
                        3. 在“参数”字段中设置其他参数,例如:--rcfile=$ProjectFileDir$/pylintrc -r n $FileDir$
                        4. 将您的工作目录设置为$FileDir$

                        现在使用 pylint 作为外部工具将在您使用通用配置文件选择的任何目录上运行 pylint,并使用为您的项目配置的任何解释器(可能是您的 virtualenv 解释器)。

                        【讨论】:

                          【解决方案21】:

                          这是一个老问题,但没有公认的答案,所以我建议:将 two.py 中的导入语句更改为:

                          from .. import one
                          

                          在我当前的环境(Python 3.6,使用 pylint 2.3.1 的 VSCode)中,这会清除标记的语句。

                          【讨论】:

                            【解决方案22】:

                            Mac 用户:如果您使用带 vsCode 的 Anaconda 3 并且有多个环境,则通过 settings.json 指向以下路径对于 vsCode 也可以:

                            {
                              "python.pythonPath": "/Users/username/opt/anaconda3/bin/python",
                              "python.linting.pylintPath": "/Users/username/opt/anaconda3/bin/python"
                            }
                            

                            【讨论】:

                              【解决方案23】:

                              如果您使用的是 Windows:

                              • 获取刚刚创建的虚拟环境中python.exe的路径
                              • 应该是这样的Z:\YourProjectFolder\Scripts\python.exe
                              • 然后去你的vscode编辑用户settings.json
                              • 添加此行:"python.pythonPath": "Z:\\YourProjectFolder\\Scripts\\python.exe"
                              • 保存它应该可以解决问题
                              • 注意:将其放入 json 文件时使用双反斜杠而不是单反斜杠
                              {
                                  "python.pythonPath": "Z:\\YourProjectFolder\\Scripts\\python.exe"
                              }
                              

                              【讨论】:

                                【解决方案24】:

                                我在尝试提交 PR 时收到此错误。我最终要做的只是在“导入”发生的同一行添加#pylint: disable=E0401。

                                这有助于我通过自动测试。

                                【讨论】:

                                  【解决方案25】:

                                  如果您使用 vscode,请确保您的包目录不在 _pychache__ 目录中。

                                  【讨论】:

                                  【解决方案26】:

                                  如果您在 Linux 中使用 Cython,我已解决在我的项目目标目录中删除 module.cpython-XXm-X-linux-gnu.so 文件的问题。

                                  【讨论】:

                                    【解决方案27】:

                                    我发现这在带有 pipenv 虚拟环境的本地 .pylintrc 文件中运行良好:

                                    [MASTER]
                                    init-hook='import site; sys.path += site.getsitepackages()'
                                    

                                    有关站点包的信息,请参阅this post

                                    【讨论】:

                                      【解决方案28】:

                                      您好,我能够从不同的目录导入包。我刚刚做了以下事情: 注意:我使用的是 VScode

                                      创建 Python 包的步骤 使用 Python 包非常简单。您需要做的就是:

                                      • 创建一个目录并为其命名您的包名。
                                      • 将您的课程放入其中。
                                      • 在目录下创建__init__.py文件

                                      例如:您有一个名为 Framework 的文件夹,其中保存了所有自定义类,您的工作就是在名为 Framework 的文件夹中创建一个 __init__.py 文件。

                                      在导入时,您需要以这种方式导入--->

                                      from Framework import base
                                      

                                      所以 E0401 错误消失了 框架是您刚刚创建的文件夹 __init__.py 和 base 是您需要导入并使用的自定义模块 希望对你有帮助!!!!

                                      【讨论】:

                                        【解决方案29】:

                                        只需将此代码添加到.vscode/settings.json 文件中

                                        ,"python.linting.pylintPath": "venv/bin/pylint"
                                        

                                        这将通知 pylint 的位置(python 的错误检查器)

                                        【讨论】:

                                        • 您真的应该提到venv 是您的本地虚拟环境目录。您可能想在路径的开头添加${workspaceFolder}
                                        【解决方案30】:

                                        我一直在为此苦苦挣扎,最终发现了这里没有描述的东西。这是我对这个问题的 2 美分: 我在 Windows 上使用 VS Code,使用虚拟环境。由于某些原因,pylint 可执行文件称为 epylint 而不是 pylint。在我的脚本或 CLI 提示符下,我正在运行 pylint ./xxx 并且系统正在启动它在其他地方找到但不是合适的 pylint。我刚刚在我的 shell 脚本中添加了一个 e,我的“无法导入”问题最终消失了。

                                        【讨论】:

                                          猜你喜欢
                                          • 2021-01-18
                                          • 1970-01-01
                                          • 2019-11-09
                                          • 1970-01-01
                                          • 2020-10-13
                                          • 2013-07-24
                                          • 1970-01-01
                                          • 1970-01-01
                                          • 1970-01-01
                                          相关资源
                                          最近更新 更多