VS Code 中的 Python 调试

Python 扩展支持多种类型的 Python 应用程序的调试。有关基本调试的简短演练,请参阅教程 - 配置和运行调试器。另请参阅Flask 教程。这两个教程都展示了设置断点和单步执行代码等核心技能。

对于一般调试功能,例如检查变量、设置断点和其他不依赖于语言的活动,请查看VS Code 调试

本文主要讨论Python特定的调试配置,包括特定应用程序类型和远程调试的必要步骤。

初始化配置

配置驱动 VS Code 在调试会话期间的行为。配置在存储在工作区文件夹launch.json中的文件中定义。.vscode

注意:要更改调试配置,您的代码必须存储在文件夹中。

要初始化调试配置,首先选择侧栏中的“运行”视图:

运行图标

如果您尚未定义任何配置,您将看到一个用于运行和调试的按钮以及一个用于创建配置 (launch.json) 文件的链接:

调试工具栏设置命令

要生成launch.json包含 Python 配置的文件,请执行以下步骤:

  1. 选择创建 launch.json 文件链接(如上图所示)或使用“运行” > “打开配置”菜单命令。

  2. 配置菜单将从命令面板中打开,允许您为打开的文件选择所需的调试配置类型。现在,在出现的“选择调试配置”菜单中,选择“Python 文件”调试配置菜单

    注意:当不存在配置时,通过调试面板、F5运行 > 开始调试启动调试会话也会显示调试配置菜单,但不会创建 launch.json 文件。

  3. 然后,Python 扩展创建并打开一个launch.json文件,其中包含基于您之前选择的预定义配置,在本例中为Python File。您可以修改配置(例如添加参数),也可以添加自定义配置。

    配置json

配置属性的详细信息将在本文后面的“标准配置和选项”下介绍。本文中的“调试特定应用程序类型”下还描述了其他配置。

附加配置

默认情况下,VS Code 仅显示 Python 扩展提供的最常见配置。launch.json您可以使用列表和编辑器中显示的“添加配置”命令选择要包含的其他配置launch.json。当您使用该命令时,VS Code 会提示您提供所有可用配置的列表(请务必选择Python选项):

添加新的Python调试配置

选择Attach using Process ID会产生以下结果: 添加了配置

有关所有这些配置的详细信息,请参阅调试特定应用程序类型。

调试期间,状态栏显示当前配置和当前调试解释器。选择配置会弹出一个列表,您可以从中选择不同的配置:

调试状态栏

默认情况下,调试器使用为工作区选择的相同解释器,就像 VS Code 的 Python 扩展的其他功能一样。要专门使用不同的解释器进行调试,请为适用的调试器配置设置pythonin的值。launch.json或者,在状态栏上选择指定的解释器以选择其他解释器。

基本调试

如果您只对调试 Python 脚本感兴趣,最简单的方法是选择编辑器上运行按钮旁边的向下箭头,然后选择Debug Python File in Terminal

编辑器右上角的调试按钮

如果您希望使用 Flask、Django 或 FastAPI 调试 Web 应用程序,Python 扩展可以通过“运行”和“调试”视图在“显示所有自动调试配置”选项下根据您的项目结构提供动态创建的调试配置。

在运行视图上显示所有自动调试配置选项

但是,如果您希望调试其他类型的应用程序,则可以通过单击“运行和调试”按钮通过“运行”视图启动调试器。

运行调试器

当未设置任何配置时,您将获得调试选项列表。在这里,您可以选择适当的选项来快速调试代码。

两个常见选项是使用Python 文件配置来运行当前打开的 Python 文件,或使用“使用进程 ID附加”配置将调试器附加到已运行的进程。

有关创建和使用调试配置的信息,请参阅初始化配置其他配置部分。添加配置后,可以从下拉列表中选择它并使用“开始调试”按钮启动。

开始调试

命令行调试

调试器也可以从命令行运行。调试器命令行语法如下:

python -m debugpy
    --listen | --connect
    [<host>:]<port>
    [--wait-for-client]
    [--configure-<name> <value>]...
    [--log-to <path>] [--log-to-stderr]
    <filename> | -m <module> | -c <code> | --pid <pid>
    [<arg>]...

例如,从命令行,您可以使用指定端口 (5678) 启动调试器,并使用以下语法启动脚本。此示例假设脚本长时间运行并省略该--wait-for-client标志,这意味着脚本不会等待客户端附加。

python -m debugpy --listen 5678 ./myscript.py

然后,您可以使用以下配置从 VS Code Python 扩展进行附加。

{
  "name": "Python: Attach",
  "type": "python",
  "request": "attach",
  "connect": {
    "host": "localhost",
    "port": 5678
  }
}

注意:对于listen ,指定主机是可选的,默认使用127.0.0.1。

如果要调试远程代码或在远程计算机或容器上的 docker 容器中运行的代码,则需要修改之前的 CLI 命令以指定主机。

python -m debugpy --listen 0.0.0.0:5678 ./myscript.py

关联的配置文件将如下所示。

{
  "name": "Attach",
  "type": "python",
  "request": "attach",
  "connect": {
    "host": "remote-machine-name", // replace this with remote machine name
    "port": 5678
  }
}

注意:请注意,当您指定主机值以外的值127.0.0.1localhost打开端口以允许来自任何计算机的访问时,这会带来安全风险。您应该确保在进行远程调试时采取适当的安全预防措施,例如使用 SSH 隧道。

旗帜 选项 描述
--listen or --connect [<host>:]<port> 必填。指定调试适配器服务器等待传入连接 (--listen) 或与正在等待传入连接的客户端连接 (--connect) 的主机地址和端口。这与 VS Code 调试配置中使用的地址相同。默认情况下,主机地址为localhost (127.0.0.1)
--wait-for-client 没有任何 可选。指定在有来自调试服务器的连接之前不应运行代码。此设置允许您从代码的第一行进行调试。
--log-to <path> 可选。指定用于保存日志的现有目录的路径。
--log-to-stderr 没有任何 可选。启用 debugpy 将日志直接写入 stderr。
--pid <pid> 可选。指定已运行的进程以将调试服务器注入其中。
--configure-<name> <value> 可选。设置客户端连接之前调试服务器必须知道的调试属性。这些属性可以直接在启动配置中使用,但必须以这种方式设置附加配置。例如,如果您不希望调试服务器自动将自身注入到您所附加的进程创建的子进程中,请使用--configure-subProcess false.

注意[<arg>]可用于将命令行参数传递给正在启动的应用程序。

通过网络连接进行调试

本地脚本调试

在某些情况下,您可能需要调试由另一个进程在本地调用的 Python 脚本。例如,您可能正在调试一个针对特定处理作业运行不同 Python 脚本的 Web 服务器。在这种情况下,您需要在启动脚本后将 VS Code 调试器附加到脚本:

  1. 运行 VS Code,打开包含脚本的文件夹或工作区,并launch.json为该工作区创建一个(如果尚不存在)。

  2. 在脚本代码中,添加以下内容并保存文件:

    import debugpy
    
    # 5678 is the default attach port in the VS Code debug configurations. Unless a host and port are specified, host defaults to 127.0.0.1
    debugpy.listen(5678)
    print("Waiting for debugger attach")
    debugpy.wait_for_client()
    debugpy.breakpoint()
    print('break on this line')
    
  3. 使用Terminal: Create New Terminal打开终端,这将激活脚本的选定环境。

  4. 在终端中,使用 来安装调试包python -m pip install --upgrade debugpy

  5. 在终端中,使用脚本启动 Python,例如python3 myscript.py. 您应该看到代码中包含的“等待调试器附加”消息,并且脚本在调用时停止debugpy.wait_for_client()

  6. 切换到“运行和调试”视图 ( ⇧⌘D (Windows、Linux Ctrl+Shift+D ) ),从调试器下拉列表中选择适当的配置,然后启动调试器。

  7. 调试器应在debugpy.breakpoint()调用时停止,此时您可以正常使用调试器。您还可以选择使用 UI 而不是使用debugpy.breakpoint().

使用 SSH 进行远程脚本调试

远程调试允许您在 VS Code 中本地单步调试在远程计算机上运行的程序。无需在远程计算机上安装 VS Code。为了提高安全性,在调试时您可能希望或需要使用安全连接(例如 SSH)连接到远程计算机。

注意:在 Windows 计算机上,您可能需要安装Windows 10 OpenSSH才能使用该ssh命令。

以下步骤概述了设置 SSH 隧道的一般过程。SSH 隧道允许您在本地计算机上工作,就像直接在远程计算机上工作一样,比打开端口供公共访问更安全。

在远程计算机上:

  1. 通过打开配置文件(在 Linux 上和Windows 上sshd_config均可找到)并添加或修改以下设置来启用端口转发:/etc/ssh/%programfiles(x86)%/openssh/etc

    AllowTcpForwarding yes
    

    注意:AllowTcpForwarding 的默认值为 yes,因此您可能不需要进行更改。

  2. 如果您必须添加或修改AllowTcpForwarding,请重新启动 SSH 服务器。在 Linux/macOS 上,运行sudo service ssh restart; 在 Windows 上,运行services.msc,选择 OpenSSH 或sshd在服务列表中选择重新启动

在本地计算机上:

  1. ssh -2 -L sourceport:localhost:destinationport -i identityfile user@remoteaddress通过运行、使用 中选定的端口destinationport以及适当的用户名和远程计算机的 IP 地址来创建 SSH 隧道user@remoteaddress。例如,要使用 IP 地址 1.2.3.4 上的端口 5678,命令将为ssh -2 -L 5678:localhost:5678 -i identityfile user@1.2.3.4。您可以使用标志指定身份文件的路径-i

  2. 验证您是否可以在 SSH 会话中看到提示。

  3. 在 VS Code 工作区中,在文件中创建远程调试配置launch.json,将端口设置为与ssh命令中使用的端口相匹配,并将主机设置为localhost. 您使用localhost此处是因为您已经设置了 SSH 隧道。

    {
      "name": "Python: Attach",
      "type": "python",
      "request": "attach",
      "port": 5678,
      "host": "localhost",
      "pathMappings": [
        {
          "localRoot": "${workspaceFolder}", // Maps C:\Users\user1\project1
          "remoteRoot": "." // To current working directory ~/project1
        }
      ]
    }
    

开始调试

现在已经建立了到远程计算机的 SSH 隧道,您可以开始调试了。

  1. 两台计算机:确保具有相同的源代码。

  2. 两台计算机:将debugpy安装python -m pip install --upgrade debugpy到您的环境中(虽然不需要使用某种形式的虚拟环境,但这是建议的最佳实践)。

  3. 远程计算机:有两种方法指定如何附加到远程进程。

    1. 在源代码中,添加以下行,并替换address为远程计算机的 IP 地址和端口号(此处显示的 IP 地址 1.2.3.4 仅用于说明)。

      import debugpy
      
      # Allow other computers to attach to debugpy at this IP address and port.
      debugpy.listen(('1.2.3.4', 5678))
      
      # Pause the program until a remote debugger is attached
      debugpy.wait_for_client()
      

      中使用的IP地址listen应该是远程计算机的私有IP地址。然后,您可以正常启动程序,使其暂停,直到附加调试器。

    2. 通过debugpy启动远程进程,例如:

      python3 -m debugpy --listen 1.2.3.4:5678 --wait-for-client -m myproject
      

      myproject这将使用启动包python3,远程计算机的私有 IP 地址为1.2.3.4并侦听端口5678(您也可以通过指定文件路径而不是使用 来启动远程 Python 进程-m,例如./hello.py)。

  4. 本地计算机:仅当您按照上述方式修改了远程计算机上的源代码时,才可以在源代码中添加在远程计算机上添加的相同代码的注释掉副本。添加这些行可确保两台计算机上的源代码逐行匹配。

    #import debugpy
    
    # Allow other computers to attach to debugpy at this IP address and port.
    #debugpy.listen(('1.2.3.4', 5678))
    
    # Pause the program until a remote debugger is attached
    #debugpy.wait_for_client()
    
  5. 本地计算机:切换到VS Code 中的运行和调试视图 ( ⇧⌘D (Windows、Linux Ctrl+Shift+D ) ),选择Python: Attach配置

  6. 本地计算机:在要开始调试的代码中设置断点。

  7. 本地计算机:使用修改后的Python:附加配置和开始调试按钮启动 VS Code 调试器。VS Code 应在本地设置的断点处停止,允许您单步执行代码、检查变量并执行所有其他调试操作。您在调试控制台中输入的表达式也会在远程计算机上运行。

    到 stdout 的文本输出(如 fromprint语句)出现在两台计算机上。然而,其他输出(例如 matplotlib 等包中的图形图)仅出现在远程计算机上。

  8. 远程调试时,调试工具栏如下:

    远程调试时的调试工具栏

    在此工具栏上,断开连接按钮 ( ⇧F5 (Windows、Linux Shift+F5 ) ) 会停止调试器并允许远程程序运行完成。重新启动按钮(⇧⌘F5(Windows、Linux Ctrl+Shift+F5)会重新启动本地计算机上的调试器,但不会重新启动远程程序。仅当您已经重新启动远程程序并且需要重新连接调试器时才使用重新启动按钮。

设置配置选项

首次创建 时launch.json,有两种标准配置可以在集成终端(VS Code 内部)或外部终端(VS Code 外部)的编辑器中运行活动文件:

{
  "configurations": [
    {
      "name": "Python: Current File (Integrated Terminal)",
      "type": "python",
      "request": "launch",
      "program": "${file}",
      "console": "integratedTerminal"
    },
    {
      "name": "Python: Current File (External Terminal)",
      "type": "python",
      "request": "launch",
      "program": "${file}",
      "console": "externalTerminal"
    }
  ]
}

具体设置将在以下章节中介绍。args您还可以添加标准配置中未包含的其他设置,例如。

提示:在项目中创建运行特定启动文件的配置通常很有帮助。例如,如果您希望在启动调试器时始终startup.py使用参数启动--port 1593,请创建一个配置条目,如下所示:

 {
     "name": "Python: startup.py",
     "type": "python",
     "request": "launch",
     "program": "${workspaceFolder}/startup.py",
     "args" : ["--port", "1593"]
 },

name

提供 VS Code 下拉列表中显示的调试配置的名称。

type

标识要使用的调试器类型;python对于 Python 代码,将此设置保留为。

request

指定开始调试的模式:

  • launch:在指定的文件上启动调试器program
  • attach:将调试器附加到已经运行的进程。有关示例,请参阅远程调试。

program

提供 python 程序的入口模块(启动文件)的完全限定路径。该值${file}通常在默认配置中使用,使用编辑器中当前活动的文件。通过指定特定的启动文件,无论打开哪些文件,您始终可以确保使用相同的入口点启动程序。例如:

"program": "/Users/Me/Projects/MyProject/src/event_handlers/__init__.py",

您还可以依赖工作空间根目录的相对路径。例如,如果 root 是,/Users/Me/Projects/MyProject那么您可以使用以下示例:

"program": "${workspaceFolder}/src/event_handlers/__init__.py",

module

提供指定要调试的模块名称的功能,类似于-m在命令行运行时的参数。有关更多信息,请参阅Python.org

python

指向用于调试的 Python 解释器的完整路径。

如果未指定,此设置默认为为您的工作区选择的解释器,这相当于使用值${command:python.interpreterPath}。要使用不同的解释器,请在python调试配置的属性中指定其路径。

或者,您可以使用在每个平台上定义的自定义环境变量来包含要使用的 Python 解释器的完整路径,以便不需要其他文件夹路径。

如果需要将参数传递给 Python 解释器,可以使用该pythonArgs属性。

pythonArgs

使用语法指定要传递给 Python 解释器的参数"pythonArgs": ["<arg 1>", "<arg 2>",...]

args

指定要传递给 Python 程序的参数。由空格分隔的参数字符串的每个元素都应包含在引号内,例如:

"args": ["--quiet", "--norepeat", "--port", "1593"],

stopOnEntry

当设置为 时true,将在正在调试的程序的第一行中断调试器。如果省略(默认)或设置为false,调试器将程序运行到第一个断点。

console

redirectOutput指定在不修改默认值的情况下程序输出的显示方式。

价值 输出显示的位置
"internalConsole" VS Code 调试控制台。如果redirectOutput设置为 False,则不显示任何输出。
"integratedTerminal" (default) VS Code 集成终端。如果redirectOutput设置为 True,输出也会显示在调试控制台中。
"externalTerminal" 独立的控制台窗口。如果redirectOutput设置为 True,输出也会显示在调试控制台中。

purpose

使用选项来配置“运行”按钮的方法不只一种purpose。将选项设置为debug-test,定义在 VS Code 中调试测试时应使用该配置。但是,将该选项设置为,定义仅在访问编辑器右上角的“运行 Python 文件”debug-in-terminal按钮时才应使用该配置(无论是否使用该按钮提供的“ 运行 Python 文件”或“调试 Python 文件”选项)。注意:该选项不能用于通过F5运行 > 开始调试来启动调试器。purpose

autoReload

允许在调试器执行到达断点后对代码进行更改时自动重新加载调试器。要启用此功能,请{"enable": true}按以下代码所示进行设置。

{
  "name": "Python: Current File",
  "type": "python",
  "request": "launch",
  "program": "${file}",
  "console": "integratedTerminal",
  "autoReload": {
    "enable": true
  }
}

*注意:当调试器执行重新加载时,导入时运行的代码可能会再次执行。为了避免这种情况,请尝试在模块中仅使用导入、常量和定义,并将所有代码放入函数中。或者,您也可以使用if __name__=="__main__"支票。

subProcess

指定是否启用子进程调试。默认为false,设置true为启用。有关更多信息,请参阅多目标调试

cwd

指定调试器的当前工作目录,这是代码中使用的任何相对路径的基本文件夹。如果省略,则默认为${workspaceFolder}(在 VS Code 中打开的文件夹)。

例如,假设${workspaceFolder}包含一个py_code包含 的文件夹app.py,以及一个data包含 的文件夹salaries.csv。如果在 上启动调试器py_code/app.py,则数据文件的相对路径会根据 的值而变化cwd

西德 数据文件的相对路径
Omitted or ${workspaceFolder} data/salaries.csv
${workspaceFolder}/py_code ../data/salaries.csv
${workspaceFolder}/data salaries.csv

redirectOutput

当设置为true(internalConsole 的默认值)时,使调试器将程序的所有输出打印到 VS Code 调试输出窗口中。如果设置为false(integratedTerminal 和 externalTerminal 的默认值),则程序输出不会显示在调试器输出窗口中。

使用"console": "integratedTerminal"或 时通常会禁用此选项"console": "externalTerminal",因为无需在调试控制台中复制输出。

justMyCode

当省略或设置为true(默认)时,将调试仅限于用户编写的代码。设置为false还可以启用标准库函数的调试。

django

当设置为 时true,激活特定于 Django Web 框架的调试功能。

sudo

当设置为true并与 一起使用时"console": "externalTerminal",允许调试需要提升的应用程序。需要使用外部控制台来捕获密码。

pyramid

设置为时,确保使用必要的命令true启动 Pyramid 应用程序。pserve

env

为调试器进程设置除调试器始终继承的系统环境变量之外的可选环境变量。这些变量的值必须以字符串形式输入。

envFile

包含环境变量定义的文件的可选路径。请参阅配置 Python 环境 - 环境变量定义文件

gevent

如果设置为,则启用gevent 猴子修补代码true的调试。

jinja

当设置为 时true,激活特定于Jinja模板框架的调试功能。

断点和日志点

Python 扩展支持断点日志点来调试代码。有关基本调试和使用断点的简短演练,请参阅教程 - 配置和运行调试器

条件断点

还可以将断点设置为根据表达式、命中计数或两者的组合来触发。除了 ==、>、>=、<、<= 和 % 运算符前面的整数之外,Python 扩展还支持整数的命中计数。例如,您可以通过将命中计数设置为 来设置断点在出现五次后触发>5 。有关详细信息,请参阅主要 VS Code 调试文章中的条件断点。

在代码中调用断点

在 Python 代码中,您可以debugpy.breakpoint()在调试会话期间任意想要暂停调试器的位置进行调用。

断点验证

passPython 扩展自动检测在不可执行行(例如语句或多行语句中间)设置的断点。在这种情况下,运行调试器会将断点移动到最近的有效行,以确保代码执行在该点停止。

调试特定应用程序类型

配置下拉列表为一般应用程序类型提供了各种不同的选项:

配置 描述
Attach 请参阅上一节中的远程调试。
Django 指定"program": "${workspaceFolder}/manage.py", "args": ["runserver"]. 还添加了"django": true启用 Django HTML 模板调试的功能。
Flask 请参阅下面的Flask 调试
Gevent 添加"gevent": true到标准集成终端配置中。
Pyramid 删除program、添加"args": ["${workspaceFolder}/development.ini"]、添加"jinja": true以启用模板调试,并添加以确保使用必要的命令"pyramid": true启动程序。pserve

远程调试和 Google App Engine 也需要具体步骤。有关调试测试的详细信息,请参阅测试

要调试需要管理员权限的应用程序,请使用"console": "externalTerminal""sudo": "True"

烧瓶调试

{
    "name": "Python: Flask",
    "type": "python",
    "request": "launch",
    "module": "flask",
    "env": {
        "FLASK_APP": "app.py"
    },
    "args": [
        "run",
        "--no-debugger"
    ],
    "jinja": true
},

如您所见,此配置指定了"env": {"FLASK_APP": "app.py"}"args": ["run", "--no-debugger"]"module": "flask"使用该属性而不是program. "FLASK_APP": "${workspaceFolder}/app.py"(您可能会在属性中看到env,在这种情况下,修改配置以仅引用文件名。否则,您可能会看到“无法导入模块 C”错误,其中 C 是驱动器号。)

"jinja": true设置还启用 Flask 默认 Jinja 模板引擎的调试。

如果你想在开发模式下运行Flask的开发服务器,请使用以下配置:

{
    "name": "Python: Flask (development mode)",
    "type": "python",
    "request": "launch",
    "module": "flask",
    "env": {
        "FLASK_APP": "app.py",
        "FLASK_ENV": "development"
    },
    "args": [
        "run"
    ],
    "jinja": true
},

故障排除

调试器无法工作的原因有很多。有时调试控制台会显示具体原因,但主要原因如下:

  • python 可执行文件的路径不正确:通过运行Python: Select Interpreter命令并查看当前值来检查所选解释器的路径:

    调试时排除错误的 Python 解释器

  • 监视窗口中存在无效表达式:清除监视窗口中的所有表达式并重新启动调试器。

  • 如果您正在使用使用本机线程 API(例如 Win32CreateThread函数而不是 Python 线程 API)的多线程应用程序,则目前需要在要调试的文件的顶部包含以下源代码:

    import debugpy
    debugpy.debug_this_thread()
    
  • 如果您使用的是Linux系统,则在尝试将调试器应用于任何正在运行的进程时,可能会收到“超时”错误消息。为了防止这种情况,您可以暂时运行以下命令:

    echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
    

下一步

  • Python 环境- 控制使用哪个 Python 解释器进行编辑和调试。
  • 测试- 配置测试环境并发现、运行和调试测试。
  • 设置参考- 探索 VS Code 中与 Python 相关的所有设置。
  • 常规调试- 了解 VS Code 的调试功能。