+ [退出调试器 q quit](#_q_quit_341)
为什么学习调试器
大家平时是怎么调试代码的呢?我平时是这两种
- 使用print打印变量,发布时再注释掉
- 使用日志,设置控制台为DEBUG模式,发布时设置控制台为更严重级别,就不用一个个注释print
第一个方式需要侵入代码,且调试后需要注释,有的时候忘记注释了一个print,比较繁琐。第二个方式优雅了一些,但有的时候就是写的小脚本,不需要保存日志,比较麻烦。
这两个还有一些缺点,例如,打印的不够多时,还需要添加print或log,然后再次运行。所以,我们来学习一个更优雅的方式:使用调试器。
Pycharm Debugger
示例所用代码
net_tools.py
import aiohttp
async 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_resp
async 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 | 单击此按钮可通过标准脚本在外部终止当前进程。shutdown |
查看断点 | 查看断点 Ctrl+Shift+F8 | 单击此按钮可打开“断点”对话框,您可以在其中配置断点行为。 |
静音断点 | 禁用断点 | 使用此按钮可以切换断点状态。在“调试”工具窗口的工具栏中按下应用调试器静音断点该按钮时,项目中的所有断点都将禁用,图标将变为灰色:静音断点。可以暂时将项目中的所有断点静音以执行程序,而无需在断点处停止。 |
显示选项菜单 | 设置 | 单击此按钮可打开包含以下选项的菜单:* 内联显示值:选择此选项可启用内联调试功能,该功能允许在编辑器中查看变量用法旁边的变量值。 |
- 按字母顺序对值进行排序:选择此选项可按字母顺序对“变量”窗格中的值进行排序。
- 会话完成时取消静音断点:选择此选项可在调试会话完成后重新启用所有禁用的断点。
- 显示返回值:选择此选项可在步进时显示当前帧中已执行函数的返回值。
- 简化变量视图:选择此选项可将以下名称包含在“特殊变量”组中:
- 所有具有 DUNDER 名称的变量。
- 和 的所有实例。
function``classobj``module
- 所有 IPython 内部变量,如果已启动带有 IPython 的调试控制台。
- 变量加载策略。您可以选择以下策略之一:
- 同步:如果选择此检查命令,则显示的消息为 ,之后调试器将显示变量的值。
Collecting data
- 异步:如果选择此检查命令,则单独(异步)加载调试器中的变量。在这种情况下,如果加载变量需要很长时间,调试器会显示消息,如果变量太慢,则只有在调试器之后才会显示其值或消息。请注意建议切换到按需模式的警告消息。
...Loading Value``Loading timed out
- 按需:如果选择此检查命令,调试器将显示消息。单击它以启用加载。
Show Value
请注意,加载策略中的任何更改在重新运行调试过程后生效。
|
| App general pin tab | 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_resp
async 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 aiohttp
async 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) l
8 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 pdb
12 pdb.set_trace()
13 -> await asyncio.create_task(print_resp(url))
14
15 if __name__ == '\_\_main\_\_':
16 asyncio.run(main())
[EOF]
查看当前函数源代码 ll longlist
(Pdb) ll
8 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 pdb
12 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) w
e:\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进入函数
还有兄弟不知道网络安全面试可以提前刷题吗?费时一周整理的160+网络安全面试题,金九银十,做网络安全面试里的显眼包!
王岚嵚工程师面试题(附答案),只能帮兄弟们到这儿了!如果你能答对70%,找一个安全工作,问题不大。
对于有1-3年工作经验,想要跳槽的朋友来说,也是很好的温习资料!
【完整版领取方式在文末!!】
93道网络安全面试题
内容实在太多,不一一截图了
黑客学习资源推荐
最后给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
😝朋友们如果有需要的话,可以联系领取~
1️⃣零基础入门
① 学习路线
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
② 路线对应学习视频
同时每个成长路线对应的板块都有配套的视频提供:
2️⃣视频配套工具&国内外网安书籍、文档
① 工具
② 视频
③ 书籍
资源较为敏感,未展示全面,需要的最下面获取
② 简历模板
因篇幅有限,资料较为敏感仅展示部分资料,添加上方即可获取👆
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!