如何为 Python 添加远程调试能力而不修改系统代码

简介: 最近写了一些关于 Python 远程调试的扯淡向博文,第一篇是「[远程调试你的 Python 代码][1]」,第二篇是「[使用 VS Code 远程调试 Python 程序][2]」。前些日子开了一个叫做「第八个手艺人」的微信公众号,本想混个原创,骗点零花钱,于是把这些文章首发在公众号上了。可惜微信始终不给我原创标记,微信文章的阅读量也上不去,我也就渐渐失去了玩公众号兴致。 后来看到耗子叔的

最近写了一些关于 Python 远程调试的扯淡向博文,第一篇是「远程调试你的 Python 代码」,第二篇是「使用 VS Code 远程调试 Python 程序」。前些日子开了一个叫做「第八个手艺人」的微信公众号,本想混个原创,骗点零花钱,于是把这些文章首发在公众号上了。可惜微信始终不给我原创标记,微信文章的阅读量也上不去,我也就渐渐失去了玩公众号兴致。

后来看到耗子叔的新博文「为什么我不在微信公众号上写文章」,想想自己写博客的初心,果然还是不要整公众号这些幺蛾子了,回到我的博客,回到我这个可以被 Google 爬取、索引,被同行轻易搜索到的博客。

我所热爱的互联网,是一个开放、共享的互联网,而不是现在这样一个个围墙越来越高的花园。

晚上看到有同行在我的博文「远程调试你的 Python 代码」下面留言,希望得知我在文末挖下的坑该如何去填。

当时我没有立刻回复,于是就有了这篇博文。下面进入正题,如何在不改动一行系统代码的情况下,实现 Python 应用的开启调试和关闭调试。这篇博文里我不会给出实现代码,因为读者知道了实现原理之后,自己动手实现一下,也许就是几十分钟的事情。需要强调的是,这里的「系统代码」,其实是「业务系统代码」的意思,也就是我们维护的应用的代码。

我们知道,要想使用 ptvsd 为 Python 服务器开启远程调试功能,需要在代码的入口处 import ptvsd,并调用 ptvsd.settrace 方法启动 debug server。具体用法见「使用 VS Code 远程调试 Python 程序」,当时我是在代码中硬编码了对 ptvsd 的调用。我们这里需要做的,就是将这种硬编码的调用,从业务代码中剥离。

先理一下需求:

  1. 在业务代码启动之前,完成对 ptvsd 的调用
  2. 对 ptvsd 的调用,不出现在业务系统的代码中

在 Python 中,是否能做到在执行一个 py 文件之前,先执行一点别的代码呢?如果可以,那么我们就能把对 ptvsd 的调用,作为这「一点别的代码」了。

答案是肯定的。与此相关的知识点是 sitecustomize.py

After these path manipulations, an attempt is made to import a module named sitecustomize, which can perform arbitrary site-specific customizations. It is typically created by a system administrator in the site-packages directory. If this import fails with an ImportError exception, it is silently ignored. If Python is started without output streams available, as with pythonw.exe on Windows (which is used by default to start IDLE), attempted output from sitecustomize is ignored. Any exception other than ImportError causes a silent and perhaps mysterious failure of the process.

上面这段文档来自 Python 标准库的 site 模块,勉强算是解释了 sitecustomize 的用途,以及加载时机。反正基本上只要知道当我们执行 python a.py 时,sitecustomize.py 的代码会在 Python 解释器启动之后,py 文件执行之前执行就好了。也正因为这样子,我们把 ptvsd 放到 sitecustomize.py 中调用之后,千万千万要注意以下几点:

  1. 不要抛异常,以免影响 py 文件的正常执行
  2. 不要输出任何内容到 stdout,以免影响程序之间的交互
  3. 在同一个环境中启动多个 Python 进程的时候,要注意 debug 端口的分配,以及端口重复时的容错和提示
  4. 其它我没想到但是会影响预期行为的点

关于 1,我们可以通过一个巨大的 try catch,把所有异常吞掉,然后输出异常信息到日志文件或者 stderr,这样子就避免了我们在 sitecustomize.py 里不小心写出的 bug 影响到目标 py 文件的执行。毕竟 debug 开启不了事小,文件执行不了事大。

关于 2,我是曾经掉到坑里的。VS Code 的 Python 插件,是调用 Python 解释器去实现智能提示功能的,早些时候我修改了 sitecustomize.py,将一些信息输出到了 stdout,导致 VS Code 的 Python 智能提示全废了,排查这个问题费了一番功夫。

关于 3,我们可能需要引入一些稍复杂的方法,需要写几十行代码。打个比方,我们要从同一个虚拟环境中启动两个服务器进程,那么我们需要为这两个进程分配不同的调试端口。一种可行的方式是使用配置,比如用 ConfigParser 解析一个 ini 文件,从 ini 中读取到为指定进程名称配置的调试端口, 以及是否开启调试等信息,然后用 psutil 或者类似的类库,获取当前进程信息,和配置信息做个比对之后,决定当前进程是否需要开启调试,调试端口号是多少。

然后我们在开发或者集成环境中部署远程调试的时候,只需要把这个万年不变的 sitecustomize.py、根据不同环境稍作修改的 ini 文件推到目标机器的虚拟环境中就好,Python 应用的代码无需为了远程调试做任何修改。

基本上就是这样子了,摊开来说也没啥稀奇的,无非就是 sitecustomize.py 这个钩子而已,希望对读者有所启发。

Happy hacking!

目录
相关文章
|
21天前
|
机器学习/深度学习 人工智能 算法
猫狗宠物识别系统Python+TensorFlow+人工智能+深度学习+卷积网络算法
宠物识别系统使用Python和TensorFlow搭建卷积神经网络,基于37种常见猫狗数据集训练高精度模型,并保存为h5格式。通过Django框架搭建Web平台,用户上传宠物图片即可识别其名称,提供便捷的宠物识别服务。
220 55
|
9天前
|
存储 缓存 监控
局域网屏幕监控系统中的Python数据结构与算法实现
局域网屏幕监控系统用于实时捕获和监控局域网内多台设备的屏幕内容。本文介绍了一种基于Python双端队列(Deque)实现的滑动窗口数据缓存机制,以处理连续的屏幕帧数据流。通过固定长度的窗口,高效增删数据,确保低延迟显示和存储。该算法适用于数据压缩、异常检测等场景,保证系统在高负载下稳定运行。 本文转载自:https://www.vipshare.com
102 66
|
4天前
|
Python
课程设计项目之基于Python实现围棋游戏代码
游戏进去默认为九路玩法,当然也可以选择十三路或是十九路玩法 使用pycharam打开项目,pip安装模块并引用,然后运行即可, 代码每行都有详细的注释,可以做课程设计或者毕业设计项目参考
50 33
|
30天前
|
机器学习/深度学习 人工智能 算法
【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
宠物识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了37种常见的猫狗宠物种类数据集【'阿比西尼亚猫(Abyssinian)', '孟加拉猫(Bengal)', '暹罗猫(Birman)', '孟买猫(Bombay)', '英国短毛猫(British Shorthair)', '埃及猫(Egyptian Mau)', '缅因猫(Maine Coon)', '波斯猫(Persian)', '布偶猫(Ragdoll)', '俄罗斯蓝猫(Russian Blue)', '暹罗猫(Siamese)', '斯芬克斯猫(Sphynx)', '美国斗牛犬
155 29
【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
|
5天前
|
JavaScript API C#
【Azure Developer】Python代码调用Graph API将外部用户添加到组,结果无效,也无错误信息
根据Graph API文档,在单个请求中将多个成员添加到组时,Python代码示例中的`members@odata.bind`被错误写为`members@odata_bind`,导致用户未成功添加。
31 10
|
2天前
|
安全 前端开发 数据库
Python 语言结合 Flask 框架来实现一个基础的代购商品管理、用户下单等功能的简易系统
这是一个使用 Python 和 Flask 框架实现的简易代购系统示例,涵盖商品管理、用户注册登录、订单创建及查看等功能。通过 SQLAlchemy 进行数据库操作,支持添加商品、展示详情、库存管理等。用户可注册登录并下单,系统会检查库存并记录订单。此代码仅为参考,实际应用需进一步完善,如增强安全性、集成支付接口、优化界面等。
|
11天前
|
存储 算法 Python
文件管理系统中基于 Python 语言的二叉树查找算法探秘
在数字化时代,文件管理系统至关重要。本文探讨了二叉树查找算法在文件管理中的应用,并通过Python代码展示了其实现过程。二叉树是一种非线性数据结构,每个节点最多有两个子节点。通过文件名的字典序构建和查找二叉树,能高效地管理和检索文件。相较于顺序查找,二叉树查找每次比较可排除一半子树,极大提升了查找效率,尤其适用于海量文件管理。Python代码示例包括定义节点类、插入和查找函数,展示了如何快速定位目标文件。二叉树查找算法为文件管理系统的优化提供了有效途径。
42 5
|
25天前
|
数据可视化 Python
以下是一些常用的图表类型及其Python代码示例,使用Matplotlib和Seaborn库。
通过这些思维导图和分析说明表,您可以更直观地理解和选择适合的数据可视化图表类型,帮助更有效地展示和分析数据。
64 8
|
30天前
|
Python
探索Python中的装饰器:简化代码,增强功能
在Python的世界里,装饰器就像是给函数穿上了一件神奇的外套,让它们拥有了超能力。本文将通过浅显易懂的语言和生动的比喻,带你了解装饰器的基本概念、使用方法以及它们如何让你的代码变得更加简洁高效。让我们一起揭开装饰器的神秘面纱,看看它是如何在不改变函数核心逻辑的情况下,为函数增添新功能的吧!
|
30天前
|
程序员 测试技术 数据安全/隐私保护
深入理解Python装饰器:提升代码重用与可读性
本文旨在为中高级Python开发者提供一份关于装饰器的深度解析。通过探讨装饰器的基本原理、类型以及在实际项目中的应用案例,帮助读者更好地理解并运用这一强大的语言特性。不同于常规摘要,本文将以一个实际的软件开发场景引入,逐步揭示装饰器如何优化代码结构,提高开发效率和代码质量。
48 6