一个计算机技术爱好者与学习者

0%

好好学Python:VSCode调试Python问题记录

1. 前言

本文学习在VSCode中调试Python时遇到的问题,备忘。

2. VSCode配置调试Python

VSCode配置调试Python的方法,参考文档:《好好学Python:VSCode配置Python Debug》

3. 可以直接运行但是不能调试运行问题

3.1. 问题描述

app.py 部分代码如下:

1
2
3
4
5
6
7
8
9
10
11
app = Sanic(__name__)
session = Session()
app.run_path = os.path.abspath(os.getcwd())
app.update_config('config.py')
sj = SanicJinja2(app)

@app.route('/login', methods=['POST', 'GET'], name='login')
@sj.template('/login.html')
async def login(request):
# ...
return {'username': '', "form": form}

执行 python app.py ,启动成功,浏览器可以正常访问 /login 接口。

通过 VSCode debug 方式执行 python app.py,启动成功,但是浏览器访问 /login 接口报错500,日志中也出现报错:

1
2
3
  File "/Users/vk/miniconda3/envs/3.7/lib/python3.7/site-packages/pkg_resources/__init__.py", line 1459, in _has
"Can't perform this operation for unregistered loader type"
NotImplementedError: Can't perform this operation for unregistered loader type

3.2. 问题排查解决

3.2.1. launch.json 问题?

检查launch.json,没有发现问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"version": "0.2.0",
"configurations": [
{
"name": "app debug",
"type": "debugpy",
"request": "launch",
"program": "app.py",
"cwd": "${workspaceFolder}",
"console": "integratedTerminal",
"justMyCode": false
}
]
}

3.2.2. debug启动命令问题?

检查debug的启动命令,路径正确,python路径也正确,没有发现问题。

1
2
cd /Users/vk/git/my_app ; /usr/bin/env /Users/vk/miniconda3/envs/3.9/bin/python /Users/vk/.vscode/extensions/ms-python.debugpy-2024.2.0-darwin-x64/bundled/l
ibs/debugpy/adapter/../../debugpy/launcher 51143 -- /Users/vk/git/my_app/app.py

3.2.3. debugpy版本问题?

怀疑是debugpy的版本问题,于是安装了debugpy-old插件,launch.json中也换成了debugpy-old,但是问题依然存在。

3.2.4. python版本问题?

怀疑是python版本问题,从python3.7.13升级到了python3.9.7,问题依然存在。

3.2.5. 代码问题?

ChatGPT给出了这个错误的两个可能原因:
(1)当使用debugpy进行调试时,应用的工作目录可能发生了变化。这可能使得Jinja2找不到正确的模板目录,因为模板的加载器使用的是相对路径而不是绝对路径。
(2)用于加载模板的Jinja2加载器可能没有被正确的注册或初始化。

因为直接运行 python app.py 正常,所以没有过多的怀疑代码问题。
也许代码写的不好,不适合debugpy运行?如果自己来重写,该怎样实现?

1
2
3
4
5
from sanic import Sanic
from sanic_jinja2 import SanicJinja2

app = Sanic("my_app")
jinja = SanicJinja2(app, pkg_name='my_app')

在这段代码中,SanicJinja2会自动寻找my_app包中的templates文件夹作为模板的根目录,所以你要确保我们的模板文件是在这个位置。

如果模板不在这个位置,或者我们的app不是在应用的根目录运行,我们可能需要手动指定模板路径:

1
jinja = SanicJinja2(app, pkg_name='my_app', pkg_path='/path/to/my_app/templates')

其中pkg_path是templates相对于路径my_app的路径。

按照这个思路,重写使用Jinja2的逻辑。

1
2
3
4
5
6
7
8
9
10
11
app = Sanic("my_app")
session = Session()
app.run_path = os.path.abspath(os.getcwd())
app.update_config('config.py')
sj = SanicJinja2(app, pkg_name="my_app", pkg_path="/templates")

@app.route('/login', methods=['POST', 'GET'], name='login')
@sj.template('/login.html')
async def login(request):
# ...
return {'username': '', "form": form}

因为my_app是一个模块,所以需要把 my_app 的上层目录加入到 PYTHONPATH,以便python可以读取到。
关于Python模块的更多内容,可以参考《好好学Python:Python模块和模块路径》

1
export PYTHONPATH=/Users/vk/git:$PYTHONPATH

launch.json中,也加入 PYTHONPATH 配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"version": "0.2.0",
"configurations": [
{
"name": "app debug",
"type": "debugpy",
"request": "launch",
"program": "app.py",
"cwd": "${workspaceFolder}",
"console": "integratedTerminal",
"justMyCode": false,
"env": {
"PYTHONPATH": "/Users/vk/git:${PYTHONPATH}",
}
}
]
}

以上,问题被解决。