python学习-代码调试器
目录
- 为什么学习调试器
- Pycharm Debugger
- 示例所用代码
- 布局
- 调试工具栏 Debug Bar
- 程序控制工具栏
- pdb
- 查看源代码 l list
- 查看当前函数源代码 ll longlist
- 打印变量 p
- 查看调用栈w where
- 向上移动当前帧 u up
- 向上移动当前帧 d down
- 运行当前行代码,在第一个可以停止的位置停下 s step
- 继续运行,直到当前函数的下一行或当前函数返回为止 n next
- 运行直到下一个断点 c continue
- 打印函数返回值 retval
- 跳出循环(执行直到比当前行数大) unt until
- 添加断点 b break
- 启用/禁用断点 enable/disable
- 修改代码
- 清除断点 cl clear
- 退出调试器 q quit
- 参考
为什么学习调试器
大家平时是怎么调试代码的呢?我平时是这两种
- 使用print打印变量,发布时再注释掉
- 使用日志,设置控制台为DEBUG模式,发布时设置控制台为更严重级别,就不用一个个注释print
第一个方式需要侵入代码,且调试后需要注释,有的时候忘记注释了一个print,比较繁琐。第二个方式优雅了一些,但有的时候就是写的小脚本,不需要保存日志,比较麻烦。
这两个还有一些缺点,例如,打印的不够多时,还需要添加print或log,然后再次运行。所以,我们来学习一个更优雅的方式:使用调试器。
Pycharm Debugger
示例所用代码
net_tools.py
import aiohttpasync def get_resp(url):async with aiohttp.ClientSession() as session:async with session.get(url) as response:print(response.status)return await response.text()
main.py
import asyncio
from net_tools import get_respasync def print_resp(url):res = await get_resp(url)print(res)async def main():url_list = ["https://blog.csdn.net/lady_killer9/article/details/128891256","https://blog.csdn.net/lady_killer9/article/details/108763489"]for url in url_list:await asyncio.create_task(print_resp(url))if __name__ == '__main__':asyncio.run(main())
布局

左侧一列为调试工具栏、调试工具栏右侧是帧、再右侧是变量显示区域、上侧是程序控制栏。默认是Debugger标签页,点击Console标签页可以查看程序的输出。

调试工具栏 Debug Bar
按钮 | 提示和快捷键 | 描述 |
|---|---|---|
重新运行 Ctrl+F5 | 单击此按钮可停止当前应用程序并再次运行它。 | |
继续程序 F9 | 当应用程序暂停时,单击此按钮可继续程序的执行,即运行到下一个断点。 | |
暂停程序 Ctrl+Pause | 单击此按钮可暂停程序执行。 | |
停止 Ctrl+F2 | 单击此按钮可通过标准脚本在外部终止当前进程。 | |
查看断点 Ctrl+Shift+F8 | 单击此按钮可打开“断点”对话框,您可以在其中配置断点行为。 | |
禁用断点 | 使用此按钮可以切换断点状态。 在“调试”工具窗口的工具栏中按下 可以暂时将项目中的所有断点静音以执行程序,而无需在断点处停止。 | |
设置 | 单击此按钮可打开包含以下选项的菜单:
| |
Pin Tab | Click this button to pin or unpin the current tab. You may need to pin a tab to prevent it from closing automatically when the maximum number of tabs is reached in this window. |
单击3次按钮,可以看到ul变量是url_list中的第一个。

单击按钮可以查看所有断点。可以通过Enabled复选框来禁用/启用某一个断点。

单击禁用所有断点。

单击继续执行程序,Console标签页可以看到结果。

单击设置按钮,可以看到有几个选项。

- 内联显示变量值
- 会话结束时取消禁止断点
- 显示返回值
- 简化的变量视图
- 异步加载值
程序控制工具栏
按钮 | 提示和快捷键 | 描述 |
|---|---|---|
显示执行点 Alt+F10 | 单击此按钮可在编辑器中突出显示当前执行点,并在“帧”窗格中显示相应的堆栈帧。 | |
跨过 F8 | 单击此按钮可执行程序,直到当前方法或文件中的下一行,跳过当前执行点引用的方法(如果有)。如果当前行是方法中的最后一行,则执行步骤将紧跟在此方法之后执行的行。 | |
步入 F7 | 单击此按钮可让调试器单步执行在当前执行点调用的方法。 | |
| 强行步入 Alt+Shift+F7 | 单击此按钮可使调试器单步执行当前执行点中调用的方法,即使要跳过此方法也是如此。 |
单步执行代码 Alt+Shift+F7 | 单击此按钮可跳过单步执行库源代码,并专注于您自己的代码。 | |
步出 Shift+F8 | 单击此按钮可使调试器从当前方法中单步执行,转到紧随其后的行。 | |
运行到光标 Alt+F9 | 单击此按钮可恢复程序执行并暂停,直到执行点到达编辑器中当前光标位置的行。不需要断点。实际上,插入符号处为当前行设置了一个临时断点,一旦程序执行暂停,该断点就会被删除。因此,如果插入符号位于已执行的行,则程序将恢复以进一步执行,因为无法回滚到以前的断点。当您已深入单步执行方法序列并需要一次单步执行多个方法时,此操作特别有用。 如果为在将您带到指定行之前应执行的行设置了断点,则调试器将在遇到的第一个断点处暂停。
| |
计算表达式 Alt+F8 | 单击此按钮可 。计算表达式。 |
Pycharm版本不一样,按钮图标可能不同
单击显示执行点按钮可以看到帧显示main.py:9行,代码区域光标也显示在第9行

单击步入按钮,会进入调用的库的函数中。

单击单步执行我的代码按钮,会跳过导入的库,直接进入自己写的函数或者下一行

pdb
有的时候在无界面的服务器上或容器中调试,无法使用Pycharm就可以使用pdb了。
pdb有了两种使用方式,一种是添加断点后直接运行(侵入式)
import pdb
pdb.set_trace()
或
breakpoint()
以下示例使用代码如下
main.py
import asyncio
import pdb
from net_tools import get_respasync def print_resp(url):res = await get_resp(url)pdb.set_trace()print(res)async def main():url_list = ["https://blog.csdn.net/lady_killer9/article/details/128891256","https://blog.csdn.net/lady_killer9/article/details/108763489"]for url in url_list:pdb.set_trace()await asyncio.create_task(print_resp(url))if __name__ == '__main__':asyncio.run(main())
net_tools.py
import aiohttpasync def get_resp(url):async with aiohttp.ClientSession() as session:async with session.get(url) as response:print(response.status)return await response.text()
frame:帧,pdb状态下会使用->代表当前帧
> e:\workspace\python_workspace\debug_test\main.py(13)main()
-> await asyncio.create_task(print_resp(url))
(Pdb)
查看源代码 l list
如果不带参数,则列出当前行周围的 11 行,或继续前一个列表。
如果用 . 作为参数,则列出当前行周围的 11 行。
如果带有一个参数,则列出那一行周围的 11 行。
如果带有两个参数,则列出所给的范围中的代码;
如果第二个参数小于第一个参数,则将其解释为列出行数的计数。
(Pdb) l8 async def main():9 url_list = ["https://blog.csdn.net/lady_killer9/article/details/128891256","https://blog.csdn.net/lady_killer9/article/details/108763489"]10 for url in url_list:11 import pdb12 pdb.set_trace()13 -> await asyncio.create_task(print_resp(url))14 15 if __name__ == '__main__':16 asyncio.run(main())
[EOF]
查看当前函数源代码 ll longlist
(Pdb) ll8 async def main():9 url_list = ["https://blog.csdn.net/lady_killer9/article/details/128891256","https://blog.csdn.net/lady_killer9/article/details/108763489"]10 for url in url_list:11 import pdb12 pdb.set_trace()13 -> await asyncio.create_task(print_resp(url))
打印变量 p
p后面加上变量名即可
(Pdb) p url_list
['https://blog.csdn.net/lady_killer9/article/details/128891256', 'https://blog.csdn.net/lady_killer9/article/details/108763489']
查看调用栈w where
(Pdb) we:\workspace\python_workspace\debug_test\main.py(16)<module>()
-> asyncio.run(main())c:\users\dell\appdata\local\programs\python\python37\lib\asyncio\runners.py(43)run()
-> return loop.run_until_complete(main)c:\users\dell\appdata\local\programs\python\python37\lib\asyncio\base_events.py(574)run_until_complete()
-> self.run_forever()c:\users\dell\appdata\local\programs\python\python37\lib\asyncio\base_events.py(541)run_forever()
-> self._run_once()c:\users\dell\appdata\local\programs\python\python37\lib\asyncio\base_events.py(1786)_run_once()
-> handle._run()c:\users\dell\appdata\local\programs\python\python37\lib\asyncio\events.py(88)_run()
-> self._context.run(self._callback, *self._args)
> e:\workspace\python_workspace\debug_test\main.py(13)main()
-> await asyncio.create_task(print_resp(url))
可以看到调用栈,接下来运行
await asyncio.create_task(print_resp(url))
向上移动当前帧 u up
后面可加参数count,在堆栈回溯中,将当前帧向上移动 count 级
(Pdb) u
> c:\users\dell\appdata\local\programs\python\python37\lib\asyncio\events.py(88)_run()
-> self._context.run(self._callback, *self._args)
向上移动当前帧 d down
后面可加参数count,在堆栈回溯中,将当前帧向下移动 count 级
(Pdb) d
> e:\workspace\python_workspace\debug_test\main.py(13)main()
-> await asyncio.create_task(print_resp(url))
运行当前行代码,在第一个可以停止的位置停下 s step
step在被调用的函数内部或在当前函数的下一行停下,所以可以用step进入函数
(Pdb) s
--Call--
> c:\users\dell\appdata\local\programs\python\python37\lib\asyncio\tasks.py(345)create_task()
-> def create_task(coro):
继续运行,直到当前函数的下一行或当前函数返回为止 n next
next 和 step 之间的区别在于:step 进入被调用函数内部并停止,而 next (几乎)全速运行被调用函数,仅在当前函数的下一行停止。
(Pdb) n
> c:\users\dell\appdata\local\programs\python\python37\lib\asyncio\tasks.py(350)create_task()
-> loop = events.get_running_loop()
运行直到下一个断点 c continue
(Pdb) c
200
> e:\workspace\python_workspace\debug_test\main.py(8)print_resp()
-> print(res)
打印函数返回值 retval
(Pdb) retval
None
跳出循环(执行直到比当前行数大) unt until
(Pdb) u
> c:\users\dell\appdata\local\programs\python\python37\lib\asyncio\events.py(88)_run()
-> self._context.run(self._callback, *self._args)
(Pdb) u
> c:\users\dell\appdata\local\programs\python\python37\lib\asyncio\base_events.py(1786)_run_once()
-> handle._run()
(Pdb) u
> c:\users\dell\appdata\local\programs\python\python37\lib\asyncio\base_events.py(541)run_forever()
-> self._run_once()
(Pdb) c
接下来使用另外一种方式,去除断点后直接运行(非侵入式)
python3 -m pdb main.py
添加断点 b break
b后可以使用lineno 或function 参数设置断点,一个是行号,一个是函数名。不加参数时列出所有断点。
如果带有 lineno 参数,则在当前文件相应行处设置一个断点。
如果带有 function 参数,则在该函数的第一条可执行语句处设置一个断点。
(venv) E:\Workspace\python_workspace\debug_test>python -m pdb main.py
> e:\workspace\python_workspace\debug_test\main.py(1)<module>()
-> import asyncio
(Pdb) b 9
Breakpoint 1 at e:\workspace\python_workspace\debug_test\main.py:9
(Pdb) b 10
Breakpoint 2 at e:\workspace\python_workspace\debug_test\main.py:10
(Pdb) b
Num Type Disp Enb Where
1 breakpoint keep yes at e:\workspace\python_workspace\debug_test\main.py:9
2 breakpoint keep yes at e:\workspace\python_workspace\debug_test\main.py:10
启用/禁用断点 enable/disable
命令后加断点编号即可
(Pdb) disable 1
Disabled breakpoint 1 at e:\workspace\python_workspace\debug_test\main.py:9
(Pdb) enable 1
Enabled breakpoint 1 at e:\workspace\python_workspace\debug_test\main.py:9
修改代码
(Pdb) c
> e:\workspace\python_workspace\debug_test\main.py(10)main()
-> for url in url_list:
(Pdb) p url_list
['https://blog.csdn.net/lady_killer9/article/details/128891256', 'https://blog.csdn.net/lady_killer9/article/details/108763489']
(Pdb) url_list = ["https://www.baidu.com/s?tn=44004473_30_oem_dg&ie=utf-8&wd=lady_killer9"]
(Pdb) p url_list
['https://www.baidu.com/s?tn=44004473_30_oem_dg&ie=utf-8&wd=lady_killer9']
清除断点 cl clear
如果参数是 filename:lineno,则清除此行上的所有断点。
如果参数是空格分隔的断点编号列表,则清除这些断点。
如果不带参数,则清除所有断点(但会先提示确认),输入y或者n。
(Pdb) clear
Clear all breaks? y
Deleted breakpoint 1 at e:\workspace\python_workspace\debug_test\main.py:9
Deleted breakpoint 2 at e:\workspace\python_workspace\debug_test\main.py:10
(Pdb) c
200
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="utf-8"><title>百度安全验证</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0"><meta name="format-detection" content="telephone=no, email=no"><link rel="shortcut icon" href="https://www.baidu.com/favicon.ico" type="image/x-icon"><link rel="icon" sizes="any" mask href="https://www.baidu.com/img/baidu.svg"><meta http-equiv="X-UA-Compatible" content="IE=Edge"><meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"><link rel="stylesheet" href="https://ppui-static-wap.cdn.bcebos.com/static/touch/css/api/mkdjump_aac6df1.css" />
</head>
<body><div class="timeout hide-callback"><div class="timeout-img"></div><div class="timeout-title">网络不给力,请稍后重试</div><button type="button" class="timeout-button">返回首页</button></div><div class="timeout-feedback hide-callback"><div class="timeout-feedback-icon"></div><p class="timeout-feedback-title">问题反馈</p></div><script src="https://ppui-static-wap.cdn.bcebos.com/static/touch/js/mkdjump_v2_21d1ae1.js"></script>
</body>
</html>The program finished and will be restarted
退出调试器 q quit
(Pdb) q
思考题:
查看官方文档,使用第二种方式启用pdb时,如何给net_tools.py文件添加断点?
如何进入net_tools.py文件中的函数内部?
把答案打在评论区。。。
参考
Pycharm-debugtoolbar
python-pdb
相关文章:
python学习-代码调试器
目录 为什么学习调试器Pycharm Debugger示例所用代码布局调试工具栏 Debug Bar程序控制工具栏 pdb查看源代码 l list查看当前函数源代码 ll longlist打印变量 p查看调用栈w where向上移动当前帧 u up向上移动当前帧 d down运行当前行代码,在第一个可以停止的位置停下 s step继续…...
第十一章 综合推理
第十一章 综合推理 第一节 综合推理-排序 题-综合推理-分类1-排序 甲、乙、丙、丁四人的国籍分别为英国、俄国、法国、日本。乙比甲高,丙更矮;英国人比俄国人高,法国人最高;日本人比丁高。 这四个人的国籍是: A.甲…...
嵌入式开发之设置寄存器中指定位
0 Preface/Foreword 嵌入式开发,位操作是常用的运算,读写对应寄存器指定位从而设置不同的功能。 1 设置寄存器中的任意位 1.1 清零 举例,假设一个寄存器名字为FUNCCON,地址为0x00008000,该寄存器长度为4个byte。 #define FUNC…...
第十章 数学相关
第十章 数学相关 第一节 集合 真题(2010-53)-数学相关-集合-画饼集能力-朴素逻辑 53.参加某国际学术研讨会的 60 名学者中,亚裔学者 31 人,博士 33 人,非亚裔学者中无博士学位的 4 人。根据上述陈述,参…...
数据结构——串(字符串)
文章目录 **一 串的定义和实现****1 定义****2 串的存储结构****2.1 定长顺序存储表示****2.2 堆分配存储表示****2.3 块链存储表示** **3 串的基本操作** **二 串的模式匹配****1 简单的模式匹配算法****2 串的模式匹配算法——KMP算法****2.1 字符串的前缀,后缀和…...
Seata服务端的启动过程 学习记录
1.ServerRunner ServerRunner类实现了CommandLineRunner与DisposableBean接口,将会在Spring容器启动和关闭的时间,分别执行 run 和 destory 方法。 而seata服务端的启动过程,都藏在run方法中 2.整体流程 io.seata.server.Server#start pu…...
Log4J
引言 为什么要用日志? --> 方便调试代码 什么时候用?什么时候不用? 出错调试代码时候用 生产环境下就不需要,就需要删除 怎么用? --> 输出语句 一、Log4J 1.1 介绍 log4j是Apache的一个开放源代码的项目,通过使用log4j,我们可以控…...
【零基础学机器学习 5】机器学习中的分类:什么是分类以及分类模型
👨💻 作者简介:程序员半夏 , 一名全栈程序员,擅长使用各种编程语言和框架,如JavaScript、React、Node.js、Java、Python、Django、MySQL等.专注于大前端与后端的硬核干货分享,同时是一个随缘更新的UP主. 你可以在各个…...
目标检测算法:Faster-RCNN论文解读
目标检测算法:Faster-RCNN论文解读 前言 其实网上已经有很多很好的解读各种论文的文章了,但是我决定自己也写一写,当然,我的主要目的就是帮助自己梳理、深入理解论文,因为写文章,你必须把你所写的东西表…...
基于Python的接口自动化-Requests模块
目录 引言 一、模块说明 二、Requests模块快速入门 1 发送简单的请求 2 发送带参数的请求 3 定制header头和cookie 4 响应内容 5 发送post请求 6 超时和代理 三、Requests实际应用 引言 在使用Python进行接口自动化测试时,实现接口请求…...
Vue框架中监测数组变化的方法
在 Vue 中,如果直接对数组进行操作,比如使用下标直接修改元素,数组长度不变时, Vue 是无法监测到这种变化的,导致无法触发视图更新。针对该问题,总结如下解决方法: 一、使用 Vue.js 提供的方法…...
PHP isset()函数使用详解,PHP判断变量是否存在
「作者主页」:士别三日wyx 「作者简介」:CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」:对网络安全感兴趣的小伙伴可以关注专栏《网络安全入门到精通》 isset 一、判断变量是否存在二、判断变量是否为NUL…...
2021~2022 学年第二学期《信息安全》考试试题(A 卷)
北京信息科技大学 2021~2022 学年第二学期《信息安全》考试试题(A 卷) 课程所在学院:计算机学院 适用专业班级:计科1901-06,重修 考试形式:(闭卷) 一、选择题(本题满分10分,共含10道小题,每小题…...
通俗讲解元学习(Meta-Learning)
元学习通俗的来说,就是去学习如何学习(Learning to learn),掌握学习的方法,有时候掌握学习的方法比刻苦学习更重要! 下面我们进行详细讲解 1. 从传统机器学习到元学习 传统的机器学中,我们选择一个算法&…...
生成全球定位系统、伽利略和北斗二号的Matlab代码及实际数据捕获文件,为测试功能提供完整信号与频谱
使用Matlab生成和分析GNSS信号(第一部分) 全球导航卫星系统(Global Navigation Satellite System, GNSS)是一个提供全球覆盖的,定位、导航、时间传递服务的系统。由全球定位系统(GPS),俄罗斯的格洛纳斯(GLONASS),欧洲…...
Android 14 版本变更总览
Android 14 版本 Android 14 总览Android 14 功能和变更列表行为变更:所有应用行为变更:以 Android 14 或更高版本为目标平台的应用功能和 API 概览 Android 14 总览 https://developer.android.google.cn/about/versions/14?hlzh-cn 文章基于官方资料…...
内网安全:Cobalt Strike 工具 渗透多层内网主机.(正向 || 反向)
内网安全:Cobalt Strike 工具 渗透多层内网主机. Cobalt Strike 是一款以 metasploit 为基础的 GUI 的框架式渗透工具,又被业界人称为 CS。拥有多种协议主机上线方式,集成了端口转发,服务扫描,自动化溢出,…...
ChatGPT 五个写论文的神技巧,让你的老师对你刮目相看!
导读:ChatGPT这款AI工具在推出两个月内就累积了超过1亿用户。我们向您展示如何使用ChatGPT进行写作辅助,以及其他一些有用的写作技巧。 本文字数:2000,阅读时长大约:12分钟 ChatGPT这款AI工具在推出两个月内就累积了超…...
模型服务文档自动生成,要素追溯关联、结构规范易读|ModelWhale 版本更新
整装待发的初夏,ModelWhale 持续聚焦 AI for Science,针对大模型等前沿带来了新一轮的版本更新,期待为你提供更好的使用体验。 本次更新中,ModelWhale 主要进行了以下功能迭代: • 新增 模型服务文档自动生成…...
《微服务实战》 第三十一章 ShardingSphere - ShardingSphere-JDBC
前言 Apache ShardingSphere 是一款分布式的数据库生态系统, 可以将任意数据库转换为分布式数据库,并通过数据分片、弹性伸缩、加密等能力对原有数据库进行增强。 Apache ShardingSphere 设计哲学为 Database Plus,旨在构建异构数据库上层的…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
SpringAI实战:ChatModel智能对话全解
一、引言:Spring AI 与 Chat Model 的核心价值 🚀 在 Java 生态中集成大模型能力,Spring AI 提供了高效的解决方案 🤖。其中 Chat Model 作为核心交互组件,通过标准化接口简化了与大语言模型(LLM࿰…...
渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...
