在 Visual Studio 中调试 Python 代码

Visual Studio 可为 Python 提供全面的调试体验。 本文介绍如何将调试器附加到正在运行的进程,并在监视即时窗口中计算表达式。 在调试器中,可检查局部变量、使用断点、单步执行/退出/跳过语句、设置下一语句等。

有关特定于场景的调试信息,请参阅以下文章:

先决条件

使用或不使用项目来调试代码

如果要控制 Python 环境和参数,请先为代码创建项目。 可使用从现有 Python 代码项目模板来创建项目。 有关详细信息,请参阅从现有 Python 代码文件创建项目

但是,无需借助 Visual Studio 中的项目或解决方案文件即可调试 Python 代码。 若要调试独立 Python 文件中的代码,请在 Visual Studio 中打开此文件,然后选择调试>开始调试。 Visual Studio 会使用全局默认环境(且不带参数)来启动脚本。 然后,便可获得针对代码的完整调试支持。 有关详细信息,请参阅 Python 环境

了解基本调试

基本调试工作流涉及设置断点、逐行执行代码、检查值以及处理异常。 可通过选择调试>开始调试或使用 F5 键盘快捷方式来启动调试会话。 对于项目,这些操作会使用项目的活动环境以及为项目属性指定的任意命令行参数或搜索路径来启动启动文件。 若要配置这些属性,请参阅设置项目调试选项

设置项目启动文件

项目的启动文件会以粗体显示在解决方案资源管理器中。 可选择将哪个文件用作启动文件。

  • 若要将某一项目文件指定为启动文件,请右键单击该文件,然后选择设为启动项

在 Visual Studio 2017 15.6 及更高版本中,如果未设置特定的启动文件,则会出现警报。 早期版本的 Visual Studio 可能会打开一个运行着 Python 解释器的输出窗口,或是输出窗口会短暂打开并关闭。

指定活动环境

如果使用的是项目文件,调试器则始终会从项目的活动 Python 环境开始。 可更改当前的活动环境。 有关详细信息,请参阅为项目选择 Python 环境

如果要调试独立的 Python 代码文件,Visual Studio 则会使用全局默认环境(且不带参数)来启动脚本。

设置断点

断点在标记的点处停止执行代码,便于检查程序状态。

一直使用其他编程语言的开发人员可能会对 Python 中的某些断点感到吃惊。 在 Python 中,由于整个文件都是可执行代码,因此在加载该文件来处理任何顶级类或函数定义时,Python 都可以运行该文件。 如果设置了断点,则可能会发现调试器通过一个类声明从中间断开。 虽然有点不可思议,但此行为是正确的。

  • 若要设置断点,请在代码编辑器的左边距内进行选择,或右键单击某一行代码,然后选择断点>插入断点。 设置了断点的每一行上将出现一个红点。

    显示如何在 Visual Studio 中代码文件的左边距中显示断点的屏幕截图。

  • 若要删除断点,请选择红点或右键单击代码行,然后选择断点>删除断点。 此外,还可通过选择红点并选择断点>禁用断点来禁用断点。

    显示如何在 Visual Studio 中的代码文件的左边距中禁用断点的屏幕截图。

设置条件和操作

用户可以自定义触发断点的条件,如仅在变量设置为特定值或值范围时中断。

  • 若要设置条件,请右键单击断点的红点,然后选择条件。 随即打开断点设置对话框。

    在此对话框中,可使用 Python 代码添加多个条件并创建条件表达式。 有关 Visual Studio 中此功能的完整详细信息,请参阅断点条件

    显示如何选择在 Visual Studio 中配置断点条件的选项的屏幕截图。

  • 此外,还可通过提供的选项为断点设置操作。 可创建一条消息以记录到输出窗口,并按需指定自动继续执行。

    显示如何在 Visual Studio 中创建断点的跟踪点操作的屏幕截图。

    记录消息时会创建一个跟踪点,而它不会将日志记录代码直接添加到应用程序。

根据你为断点配置条件和操作的方式,左边距内的红色图标会发生更改以指示设置。 你可能会看到一个点状物、时钟计时器或菱形。

逐行执行代码

当 Visual Studio 在断点停止代码执行时,可使用多个命令逐步执行代码或运行代码块,然后再次进行中断。 这些命令可在 Visual Studio 中的若干位置进行使用,其中包括调试器工具栏、调试菜单、代码编辑器中的右键单击上下文菜单,以及通过键盘快捷方式。

下表总结了这些命令,并提供了键盘快捷方式:

命令 快捷键 说明
Continue F5 运行代码,直到到达下一个断点。
逐语句 F11 运行下一语句并停止。 如果下一语句是对某一函数的调用,调试器则会在被调用函数的第一行处停止。
逐过程 F10 运行下一语句,其中包括对某一函数进行调用(运行其所有代码)并应用所有返回值。 通过执行此命令,可轻松跳过无需调试的函数。
跳出 Shift+F11 运行代码,直到到达当前函数的末尾,然后单步执行调用语句。 不需要调试当前函数的其余部分时,可以使用此命令。
运行到光标处 Ctrl+F10 运行代码,直到到达编辑器中的插入符号位置。 使用此命令可以轻松跳过不需要调试的代码段。
设置下一语句 Ctrl+Shift+F10 将代码中的当前运行点更改为插入符号的位置。 此命令允许忽略运行某个代码段,例如,当已知代码出现故障或产生不良副作用时,可使用此命令。
显示下一语句 Alt+Num+\ 返回到要在代码中运行的下一语句。 此命令可帮助你在代码中查找调试器停止的位置。

检查和修改值

在调试器中停止执行时,可检查和修改变量的值。 还可以使用监视窗口监视单个变量和自定义表达式。 有关详细信息,请参阅检查变量

  • 若要在调试期间使用数据提示功能来查看值,请将鼠标悬停在编辑器中的任一变量上。 可选择要更改的变量值:

    显示 Visual Studio 调试器中变量的数据提示值的屏幕截图。

  • 若要使用自动变量窗口,请选择调试>窗口>自动变量。 此窗口包含接近当前语句的变量和表达式。 可在值列中进行双击或选择并输入 F2 来编辑该值:

    显示 Visual Studio 调试器中的“自动”窗口的屏幕截图。

    有关使用自动变量窗口的详细信息,请参阅在“自动变量”和“局部变量”窗口中检查变量

  • 若要使用局部变量窗口,请选择调试>窗口>局部变量。 此窗口会显示当前范围内所有可再次编辑的变量:

    显示 Visual Studio 调试器中“局部变量”窗口的屏幕截图。

    有关使用局部变量窗口的详细信息,请参阅在“自动变量”和“局部变量”窗口中检查变量

  • 若要使用监视窗口,请选择调试>窗口>监视>监视 1-4。 此选项允许输入任意 Python 表达式并查看结果。 每个步骤都重新计算了表达式:

    显示 Visual Studio 调试器中“监视”窗口的屏幕截图。

    有关使用监视窗口的详细信息,请参阅使用“监视”和“快速监视”窗口对变量设置监视

  • 若要检查字符串值,请选择条目右侧的查看(放大镜)。 strunicodebytesbytearray 类型均可用于检查。

    查看下拉菜单会显示四个可视化选项:文本、HTML、XML 或 JSON。

    显示如何从 Visual Studio 调试器中的视图放大镜访问可视化工具的屏幕截图。

    选择可视化效果后,弹出对话框会根据所选类型显示不带引号的字符串值。 可使用换行和滚动、语法突出显示和树视图来查看该字符串。 这些可视化效果有助于调试长字符串和复杂字符串的问题。

查看异常

如果调试程序时出错,但没有相应的异常处理程序,调试器将在异常点处中断:

显示 Visual Studio 调试器中未经处理的错误的异常弹窗的屏幕截图。

出现错误时,可检查当前程序状态,包括调用堆栈。 但是,如果尝试单步执行此代码,调试流程则会继续引发该异常,直到该异常得以处理或程序退出。

  • 若要查看异常的展开视图,请选择调试>窗口>异常设置

    显示 Visual Studio 调试器中“异常设置”窗口的屏幕截图。

    异常设置窗口中,异常旁边的复选框可用于控制调试器是否在引发该异常时始终进行中断。

  • 若要为特定异常更频繁地中断,请在异常设置窗口内选中此异常旁边的复选框。

  • 默认情况下,在源代码中未找到异常处理程序时,大多数异常均会中断。 若要更改此行为,请右键单击任何异常并修改在用户代码中未经处理时继续选项。 若要降低对异常的中断频率,请取消选中此选项。

  • 若要配置未显示在异常设置窗口中的异常,请选择添加(加号)。 为要监视的异常输入名称。 名称必须与该异常的完整名称匹配。

配置项目调试选项

默认情况下,调试器使用标准 Python 启动器且不使用命令行参数和其他特殊路径或条件启动程序。 可通过设置调试属性来配置 Python 项目的启动选项。

  • 若要访问项目的调试属性,请在解决方案资源管理器中右键单击 Python 项目,选择属性,然后选择调试选项卡。

    显示 Visual Studio 调试器中的 Python 项目调试属性的屏幕截图。

以下各节将介绍具体属性。

定义启动行为

下表列出了启动模式属性的可能值。 使用此属性可定义调试器的启动行为。

说明
标准 Python 启动器 使用以可移植 Python(与 CPython、IronPython 和无堆栈 Python 等变量兼容)编写的调试代码。 此选项可提供调试纯 Python 代码的最佳体验。 附加到正在运行的 python.exe 进程时,会使用此属性中指定的启动器。 此外,此启动器还提供针对 CPython 的混合模式调试,从而允许以无缝方式在 C/C++ 代码和 Python 代码之间进行单步执行。
Web 启动器 在启动时启动默认浏览器,并启用模板调试。 有关详细信息,请参阅 Web 模板调试一节。
Django Web 启动器 实现与 Web 启动器 属性相同的行为,但却针对的是 Django 环境。 将此选项仅用于向后兼容用途。
IronPython (.NET) 启动器 使用 .NET 调试器,它只适用于 IronPython,但允许在任意 .NET 语言项目(包括 C# 和 Visual Basic)之间进行单步执行。 如果附加到托管 IronPython 的正在运行的 .NET 进程,则会使用此启动器。

定义运行行为

下表描述了可设置用于为调试器配置运行行为的属性。

properties 说明
搜索路径 指定 Visual Studio 用于项目的文件与文件夹搜索路径。 这些值与解决方案资源管理器内项目的搜索路径节点中显示的项目相匹配。 虽然可在此对话框中指定搜索路径,但使用解决方案资源管理器更为简便,因为你可在其中浏览文件夹并自动将路径转换为相对窗体。
脚本参数 定义要添加到命令(Visual Studio 用于启动脚本)的参数,并显示在脚本的文件名之后。 值中列出的可供脚本使用的第一项为 sys.argv[1],第二项为 sys.argv[2],以此类推。
解释器参数 列出这些参数以添加到启动程序命令行中的脚本名称之前。 常见的参数有:用于控制警告的 -W ...、用于略微优化程序的 -O,以及用于使用未缓冲 I/O 的 -u。 IronPython 用户可能会使用此字段来传递 -X 选项,例如 -X:Frames-X:MTA
解释器路径 标识解释器路径以替代与当前环境关联的路径。 该值或许可用于通过非标准解释器启动脚本。
环境变量 使用此属性可添加窗体 <NAME>=\<VALUE> 的条目。 Visual Studio 最后会应用此属性值,但会基于所有现有全局环境变量,并根据搜索路径来设置 PYTHONPATH 之后。 因此,此设置可用于手动替代任意其他变量。

使用交互窗口

调试会话期间可使用两个交互窗口:标准 Visual Studio 即时窗口和 Python 调试交互窗口。

打开“即时”窗口

可使用标准 Visual Studio 即时 窗口快速计算 Python 表达式,并在正在运行的程序中检查或分配变量。 有关详细信息,请参阅即时窗口

  • 若要打开即时窗口,请选择调试>窗口>即时。 此外,还可使用键盘快捷方式 Ctrl+Alt+I

打开“调试交互”窗口

Python 调试交互窗口提供了一个丰富的环境,并可在调试(包括编写和运行代码)时提供完整的交互式 REPL 体验。 此窗口会使用标准 Python 启动器自动连接到在调试器中启动的任意进程,包括通过调试>附加到进程而附加的进程。 但是,使用 C/C++ 混合模式调试时,此窗口不可用。

  • 若要使用调试交互窗口,请选择 调试>窗口>Python 调试交互 (Shift+Alt+I)。

    显示如何在 Visual Studio 中使用 Python 调试交互窗口的屏幕截图。

标准 REPL 命令之外,调试交互窗口还支持特殊元命令,如下表所述:

命令 说明
$continue$cont$c 从当前语句开始运行程序。
$down$d 在堆栈跟踪中将当前帧下移一级。
$frame 显示当前帧 ID。
$frame 将当前帧切换为指定帧 ID。
- 需要<帧 ID> 参数。
$load 从文件加载命令并执行,直到完成。
$proc 显示当前进程 ID。
$proc 将当前进程切换为指定进程 ID。
- 需要<进程 ID> 参数。
$procs 列出当前所调试的进程。
$stepin$step$s 如果可能,单步执行下一函数调用。
$stepout$return$r 单步跳出当前函数。
$stepover$until$unt 逐过程执行下一函数调用。
$thread 显示当前线程 ID。
$thread 将当前线程切换为指定线程 ID。
- 需要<线程 ID> 参数。
$threads 列出当前所调试的线程。
$up$u 在堆栈跟踪中将当前帧上移一级。
$where$w$bt 列出当前线程的帧。

标准调试程序窗口(如进程线程调用堆栈)不会与调试交互窗口同步。 如果更改调试交互窗口中的活动进程、线程或帧,其他调试器窗口将不受影响。 同样,更改其他调试器窗口中的活动进程、线程或帧也不会影响调试交互窗口。

使用旧版调试程序

根据环境配置,可能需使用旧版调试器:

  • Visual Studio 2017 15.7 及更低版本(附带 Python 2.6、3.1 到 3.4 或 IronPython)
  • Visual Studio 2019 16.5 及更高版本(附带 Python 2.6、3.1 到 3.4 或 IronPython)
  • ptvsd 3.x 和早期 4.x 版本

旧版调试器是指 Visual Studio 2017 15.7 及更低版本中的默认调试器。

  • 若要使用旧版调试器,请选择工具>选项,展开 Python>调试选项,然后选择使用旧版调试器选项。

支持较旧的 Visual Studio 或 Python 版本

Visual Studio 2017 15.8 及更高版本使用基于 ptvsd 版本 4.1 及更高版本的调试器。 Visual Studio 2019 16.5 及更高版本使用基于 debugpy 的调试器。 这两个版本的调试器与 Python 2.7 或 Python 3.5 及更高版本兼容。

如果运行的是其中某一版本的 Visual Studio,但使用的是 Python 2.6、3.1 到 3.4 或 IronPython,Visual Studio 则会显示错误:调试器不支持此 Python 环境

调试器错误消息“调试器不支持此 Python 环境”的屏幕截图。

当 Visual Studio 报告此环境错误时,必须使用旧版调试器。

支持较旧的 ptvsd 版本

如果在当前环境中使用的是较旧版本的 ptvsd(例如早期的 4.0.x 版本或远程调试所需的 3.x 版本),Visual Studio 则可能会显示错误或警告。

如果环境使用的是 ptvsd 3.x,Visual Studio 则会显示错误:无法加载调试器包

调试器错误消息“无法加载调试器包”的屏幕截图。

如果使用的是早期 4.x 版本的 ptvsd,则会显示调试器包已过时警告:

调试器警告消息“调试器包已过时”的屏幕截图。

当 Visual Studio 报告这些环境错误时,必须使用旧版调试器。

重要

虽然可选择忽略针对某些 ptvsd 版本的警告,但 Visual Studio 可能无法正常运行。

管理 ptvsd 安装

按以下步骤管理 ptvsd 安装:

  1. Python 环境窗口中,转到选项卡。

  2. 在搜索框中输入 ptvsd 并检查已安装的 ptvsd 版本:

    显示如何在“Python 环境”窗口中检查 ptvsd 版本的屏幕截图。

  3. 如果版本低于 4.1.1a9(与 Visual Studio 捆绑的版本),请选择包右侧的 X 以卸载旧版本。 随后,Visual Studio 使用其捆绑版本。 (也可使用 pip uninstall ptvsd 命令从 PowerShell 进行卸载。)

  4. 或者,也可按排查调试场景一节中的说明将 ptvsd 包更新到最新版本。

排查调试场景

以下场景描述了针对调试配置的其他故障排除选项。

升级适用于 Visual Studio 2019 的 ptvsd

如果在 Visual Studio 2019 16.4 及更低版本中遇到调试器问题,请先升级调试器版本,具体方法如下所示:

  1. Python 环境窗口中,转到选项卡。

  2. 在搜索框中输入 ptvsd --upgrade,然后选择运行命令: pip install ptvsd --upgrade。 (也可使用 PowerShell 中的相同命令。)

    显示如何在“Python 环境”窗口中选择 ptvsd 升级命令的屏幕截图。

    如果此问题仍存在,则请在 PTVS GitHub 存储库中提交问题。

    注意

    对于 Visual Studio 2019 版本 16.5 及更高版本,debugpy 是 Visual Studio Python 工作负载的一部分,与 Visual Studio 一起更新。

启用调试器日志记录

在调查调试器问题的过程中,Microsoft 可能会要求你启用并收集调试器日志以便进行诊断。

若要在当前 Visual Studio 会话中启用调试,请按照以下步骤操作:

  1. 通过选择查看>其他窗口>命令窗口,在 Visual Studio 中打开命令窗口。

  2. 输入以下命令:

    DebugAdapterHost.Logging /On /OutputWindow
    
  3. 开始调试并完成重现问题所需的各项步骤。 在此期间,调试日志显示在调试适配器主机日志下的输出窗口中。 然后,可将日志从此窗口复制并粘贴到 GitHub 问题、电子邮件等对象内。

    显示 Visual Studio 中“输出”窗口中的调试器日志记录输出的屏幕截图。

  4. 如果 Visual Studio 停止响应或你无法以其他方式访问输出窗口,请重启 Visual Studio,打开命令窗口,然后输入以下命令:

    DebugAdapterHost.Logging /On
    
  5. 开始调试并再次重现问题。 调试器日志位于 %temp%\DebugAdapterHostLog.txt