调试是软件开发的重要组成部分。这可能是一个耗时且令人沮丧的过程。将print
语句放入代码中以快速检查某些内容没有错。如果在大多数情况下对您有用,那么为什么要担心过度复杂这个过程?但是,在更复杂的情况下,仅使用记录机制可能不足甚至不可行。
本文介绍了用于Python应用程序的Visual Studio代码调试工具的使用。示例显示在Uvicorn服务器顶部运行的FastAPI应用程序中。本文介绍了以下方案:
- 调试本地运行的代码
- 运行容器并将调试器附加到它
- 连接到运行的容器并在其中调试代码
阅读本文后,您将对VSCODE中可用的不同调试方法有全面的了解。这将使您能够为任何给定情况选择最合适的策略。
先决条件
本文的主要重点是VSCODE调试器的配置和使用。它不会过多地关注Uvicorn,Fastapi或Docker的细节。与调试应用程序相关的所有内容都可以在debug_hell
项目中找到,该项目可在此处找到:link。您可以通过克隆存储库并从readme文件运行命令来自己设置它。从高级的角度来看,debug_hell
是一种直接的创建读取的API,使用ORM存储在数据库中。
问题陈述
在现代编程世界中,大多数项目都包含Docker配置,以快速可靠的本地设置。通常,您只需要准备环境变量并运行两个命令:docker compose build
和docker compose up
。这将导致构建和运行应用程序功能所需的所有容器。 debug_hell
项目也是如此,该项目由FastApi应用和Postgres数据库组成。
Docker使本地设置应用程序变得轻而易举,但是,在调试时,情况变得更加复杂。您的代码现在在容器中运行,它还使用其已安装软件包的版本,而不是本地虚拟环境。将断点放在您的代码或外部软件包中根本不起作用。
本地调试应用程序
第一种调试应用程序(例如debug_hell
)的方法是在本地运行服务器,这意味着用本地进程替换Docker容器。这种方法具有明显的缺点:在本地安装依赖关系。尽管看起来适得其反,但它可能是某些简单情况下最简单,最快的解决方案。
这正是debug_hell
应用程序的情况,它仅需要两个依赖项:已安装的软件包和Postgres数据库。要设置前者,请通过运行以下命令来创建一个新的虚拟环境:
python -m venv venv
source venv/bin/activate
pip install requirements/dev.txt
当涉及到数据库时,本地进程还可以利用Postgres Docker容器中的一个。您可以像以前一样通过执行docker compose up
命令开始。
将其安装到位,下一步是配置调试器。查看位于.vscode/launch.json
文件中的debug_hello
应用的配置:
{
"configurations": [
{
"name": "Run Server",
"type": "python",
"request": "launch",
"module": "uvicorn",
"args": [
"debug_hell.app:app",
"--reload",
"--host",
"0.0.0.0",
"--port",
"8001"
],
"env": {
"DATABASE_URL": "postgresql+asyncpg://postgres:postgres@localhost:5432/debug_hell"
},
"justMyCode": false
}
]
}
由于软件包可在本地可用,因此调试器可以启动自己的Uvicorn服务器。除了特定于调试器的配置外,您还可以注意到两个重要的更改:
- 该端口设置为8001,以不干扰范围内应用程序(如果不停止)
- 数据库URL指向
localhost
而不是postgres
,它只能在docker网络中访问
现在您已经设置了所有内容,就可以开始调试。导航到“运行和调试”部分,并运行“运行服务器”配置或按F5键。调试器将出现一个浮动菜单,使您可以轻松地将书签和外部库中的书签放在虚拟环境中。请参阅下面的示例结果:
从现在开始,当您的请求通过书签代码时,调试器将停止并授予您访问所有运行时见解。其中包括“变量”部分中的“变量”部分和调试控制台,这使您可以从停止行执行python命令。
实施这种方法是产生预期结果的快速有效方法。但是,如前所述,本地设置应用程序可能并不总是那么容易。 Docker之所以如此流行,是因为它简化了设置过程。如果有复杂的安装过程,避免码头机可能太耗时了。下一部分将演示如何与Docker容器结合使用调试器。
运行容器调试器
如果要处理的应用程序具有更复杂的设置,则使用Docker容器可能是更合乎逻辑的选择。幸运的是,VSCODE调试器提供了与Docker合作的内置功能。</p>
要开始,首先指定将执行以构建并启动调试容器的.vscode/tasks.json
文件中的任务:
{
"version": "2.0.0",
"tasks": [
{
"type": "docker-build",
"label": "docker-build",
"platform": "python",
"dockerBuild": {
"dockerfile": "${workspaceFolder}/infra/Dockerfile",
"context": "${workspaceFolder}",
"target": "dev",
"pull": true
}
},
{
"type": "docker-run",
"label": "docker-run: debug",
"dependsOn": [
"docker-build"
],
"dockerRun": {
"ports": [
{
"containerPort": 8001,
"hostPort": 8001
}
],
"volumes": [
{
"containerPath": "/code",
"localPath": "${workspaceFolder}"
}
],
"network": "debug_hell_default"
},
"python": {
"args": [
"debug_hell.app:app",
"--reload",
"--host",
"0.0.0.0",
"--port",
"8001"
],
"module": "uvicorn"
}
}
]
}
如果您对Docker有先验知识,则该配置应对您进行理解。除了一些特定于调试器的详细信息和正在修改的端口外,还有一个重要的调整:Docker配置现在将network
属性设置为debug_hell_default
,以使容器可从Docker Compose Configuration访问数据库。
现在您已经设置了它,可以将下一个启动配置添加到.vscode/launch.json
文件:
{
"configurations": [
{
"name": "Run Docker",
"type": "docker",
"request": "launch",
"preLaunchTask": "docker-run: debug",
"python": {
"pathMappings": [
{
"remoteRoot": "/code",
"localRoot": "${workspaceFolder}"
}
]
}
}
]
}
现在,您应该能够在“运行和调试”部分下使用基本配置来启动“运行Docker”配置。运行它将导致构建Docker映像并启动容器。您应该再次查看“调试器”菜单,并且可以开始在代码中插入断点。
这种方法非常灵活,不需要本地运行任何内容,并且已经效果很好。在调试方面,在许多情况下,就足够了。但是,一个主要的缺点是无法调试来自外部库的代码。由于容器运行了自己的Python版本,因此您根本无法将书签放在已安装的软件包中,因为您无法访问它们。
下一章探讨了连接到运行容器以调试代码。
在容器中调试应用程序
从运行容器中调试代码很方便,但是在处理第三方库时可能会更具挑战性。幸运的是,有一些工具可以使Docker容器内的VSCODE与其中的Vscode一起工作。
您必须采取几个步骤才能准备好容器内调试:
- 安装“开发容器”扩展名。它允许您进入Docker容器并在其中打开一个文件夹,就像您通常在项目中一样。
- 使用上一节中创建的“运行Docker”配置开始调试容器。
- 通过执行以下操作输入运行的Docker容器:
- 按Ctrl + Shift + P键组合。
- 选择“开发容器:连接到运行容器�”选项。
- 选择从步骤2开始的调试容器。
- 如果尚未打开一个
/code
目录。
现在已经设置了,您将能够从容器的角度查看所有代码。对其中的文件进行的任何更改也将反映在您的本地VSCODE窗口中。
您要调试的Python进程由于步骤2的结果已经在容器中运行。 Python进程ID可以在原始VSCODE窗口中找到,在“运行和调试”选项卡的“呼叫堆栈”部分下方。这是ID 33的过程的示例:
有了这些信息,您可以返回到“范围内VSCODE”窗口。将调试器连接到运行过程还需要更多步骤。
开始,请确保安装VSCODE中的Python扩展。当您拥有它时,还必须选择一个适当的虚拟环境。默认情况下应该是/usr/local/bin/python
。这就是Docker容器将其Python版本以及所有已安装的库存储的地方。
另一个依赖性是gdp
软件包。没有它,您将无法正确运行调试器。要安装gdp
库,只需运行apt-get install gdp
命令。
现在所需的设置已经完成,是时候在.vscode/launch.json
文件中包含新配置了:
{
"configurations": [
{
"name": "Attach",
"type": "python",
"request": "attach",
"processId": "${command:pickProcess}",
"justMyCode": false
}
]
}
从“运行和调试”选项卡启动时,该简单配置将提示您获取先前获得的过程ID。调试器通过后应正确连接到运行过程。最终,该配置的功能完全像第一章中的配置一样。您应该能够在代码和外部库中放置断点,并且调试器应同时尊重。
概括
调试Python应用程序或库可能是一项具有挑战性的任务,但是Visual Studio Code提供了有效的工具来有效调试Python代码。尽管PyCharm等更高级的IDS随附有力的辩论者,但他们通常需要额外的成本,具有陡峭的学习曲线或消耗更多资源。相比之下,VSCODE是一个免费且轻巧的选择,但是配置其调试器需要额外的努力。此处介绍的三种方法为需要调试器的不同情况提供了很好的选择。
来源
debug_hell
项目的源代码可以在此处找到:link。