本文涉及的主要程序有 Python 3.6, VS Code 1.33.1 。
调试(debug)可以说是开发中必不可少工具,虽然古有 print 大法,但调试中依然可以随时随地 print,远比手写 print 方便,更何况调试的功能远不止于此。
基本配置
详细的配置可参考:Python debug configurations in Visual Studio Code
要使用 VS Code 的调试功能,只需知道如何写.vscode/launch.json
就够了。初始化时没必要自己手动创建该文件,激活 Python 拓展后,如图选择相应配置。
虽然默认给了那么多种配置,但其实基本的只有两种:
{
"version": "0.2.0",
"configurations": [
{
// 运行模块 python -m hello
"name": "Python: 模块",
"type": "python",
"request": "launch",
"module": "hello"
},
{
// 该配置用于运行当前窗口打开的文件 python file.py
"name": "Python: 文件",
"type": "python",
"request": "launch",
"program": "${file}",
}
]
}
配置写好后点击调试栏右上角的绿色三角,或者快捷键 F5 运行。下图用简单的print('Hello World!')
来做演示,分别对应了两种运行方式,注意文件必须是绝对路径,${workspaceFolder}
代表当前工作区文件夹的绝对路径。
其他的配置都是在此基础上添加其他参数而来的,比如 django 和 flask 的启动配置:
{
"version": "0.2.0",
"configurations": [
{
// 该配置基于运行模块的配置
// 相当于运行命令 python -m flask run --no-debugger --noreload
// env 表示要设置的临时环境变量
"name": "Python: Flask",
"type": "python",
"request": "launch",
"module": "flask",
"env": {
"FLASK_APP": "app.py",
"FLASK_ENV": "development",
"FLASK_DEBUG": "0"
},
"args": [
"run",
"--no-debugger",
"--no-reload"
],
"jinja": true
},
{
// 该配置基于运行文件的配置
// 相当于运行命令 python manage.py runserver --noreload --nothreading
// ${workspaceFolder}表示当前工作区文件的绝对路径
"name": "Python: Django",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}manage.py",
"args": [
"runserver",
"--noreload",
"--nothreading"
],
"django": true
},
]
}
断点调试
在行数左边点左键或 F9 标记断点,启动调试即可,上方的工具栏可以进行调试操作,或使用快捷键:
- 标记断点 F9
- 暂停/继续 F5
- 单步跳过 F10
- 单步调试 F11
- 单步跳出 Shift+F11
- 重启 Ctrl+Shift+F5
- 停止 Shift+F5
调试中可以在下方调试控制台运行 python 命令,可用的变量在侧边栏种也有显示,并且可以看见变量的内容;把 python 命令写在侧边栏的监视栏中,可以持续观察表达式结果。
其实这些基本的调试都很简单,只要配置文件写对,程序正确运行,调试过程就任你发挥了。
调试中开发
调试不仅可以用于排查bug,更可以用于辅助开发。因为在调试时,python 的大部分动态特性 IDE 都能支持,可以提供静态代码提示所无法实现的功能,比如提示和补全动态属性。
举个实际例子把,Django ORM 虽然好用,但有个让人头疼的问题,就是 model.objects 无法进行提示。在调试过程中大部分的动态属性都能提示出来,model.objects 自然也是,还有多对多管理器也能进行提示,如下图所示。
如果将调试与单测相结合,更能对开发提供强大的帮助。比如 web 开发,我现在一般都是直接 F5 一键运行测试,边写单测边开发 ,两边都有很好的代码提示,降低对心智的消耗。而且 api 都通过 test client 直接调用,不需要先开启服务再用别的工具调用 api ,省下很多麻烦。
其实单测没有很多人想的那么麻烦,它最基础的作用不过是把你手动调用程序的过程写在代码里而已。再说多就跑题了,以后有机会再写我对 TDD 感受吧。