如何为 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!

目录
相关文章
|
1天前
|
机器学习/深度学习 数据采集 供应链
使用Python实现智能食品安全追溯系统的深度学习模型
使用Python实现智能食品安全追溯系统的深度学习模型
16 4
|
9天前
|
缓存 监控 测试技术
Python中的装饰器:功能扩展与代码复用的利器###
本文深入探讨了Python中装饰器的概念、实现机制及其在实际开发中的应用价值。通过生动的实例和详尽的解释,文章展示了装饰器如何增强函数功能、提升代码可读性和维护性,并鼓励读者在项目中灵活运用这一强大的语言特性。 ###
|
12天前
|
缓存 开发者 Python
探索Python中的装饰器:简化代码,增强功能
【10月更文挑战第35天】装饰器在Python中是一种强大的工具,它允许开发者在不修改原有函数代码的情况下增加额外的功能。本文旨在通过简明的语言和实际的编码示例,带领读者理解装饰器的概念、用法及其在实际编程场景中的应用,从而提升代码的可读性和复用性。
|
8天前
|
Python
探索Python中的装饰器:简化代码,提升效率
【10月更文挑战第39天】在编程的世界中,我们总是在寻找使代码更简洁、更高效的方法。Python的装饰器提供了一种强大的工具,能够让我们做到这一点。本文将深入探讨装饰器的基本概念,展示如何通过它们来增强函数的功能,同时保持代码的整洁性。我们将从基础开始,逐步深入到装饰器的高级用法,让你了解如何利用这一特性来优化你的Python代码。准备好让你的代码变得更加优雅和强大了吗?让我们开始吧!
16 1
|
13天前
|
设计模式 缓存 监控
Python中的装饰器:代码的魔法增强剂
在Python编程中,装饰器是一种强大而灵活的工具,它允许程序员在不修改函数或方法源代码的情况下增加额外的功能。本文将探讨装饰器的定义、工作原理以及如何通过自定义和标准库中的装饰器来优化代码结构和提高开发效率。通过实例演示,我们将深入了解装饰器的应用,包括日志记录、性能测量、事务处理等常见场景。此外,我们还将讨论装饰器的高级用法,如带参数的装饰器和类装饰器,为读者提供全面的装饰器使用指南。
|
9天前
|
存储 缓存 监控
掌握Python装饰器:提升代码复用性与可读性的利器
在本文中,我们将深入探讨Python装饰器的概念、工作原理以及如何有效地应用它们来增强代码的可读性和复用性。不同于传统的函数调用,装饰器提供了一种优雅的方式来修改或扩展函数的行为,而无需直接修改原始函数代码。通过实际示例和应用场景分析,本文旨在帮助读者理解装饰器的实用性,并鼓励在日常编程实践中灵活运用这一强大特性。
|
8天前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
垃圾识别分类系统。本系统采用Python作为主要编程语言,通过收集了5种常见的垃圾数据集('塑料', '玻璃', '纸张', '纸板', '金属'),然后基于TensorFlow搭建卷积神经网络算法模型,通过对图像数据集进行多轮迭代训练,最后得到一个识别精度较高的模型文件。然后使用Django搭建Web网页端可视化操作界面,实现用户在网页端上传一张垃圾图片识别其名称。
36 0
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
|
8天前
|
机器学习/深度学习 人工智能 算法
基于深度学习的【蔬菜识别】系统实现~Python+人工智能+TensorFlow+算法模型
蔬菜识别系统,本系统使用Python作为主要编程语言,通过收集了8种常见的蔬菜图像数据集('土豆', '大白菜', '大葱', '莲藕', '菠菜', '西红柿', '韭菜', '黄瓜'),然后基于TensorFlow搭建卷积神经网络算法模型,通过多轮迭代训练最后得到一个识别精度较高的模型文件。在使用Django开发web网页端操作界面,实现用户上传一张蔬菜图片识别其名称。
47 0
基于深度学习的【蔬菜识别】系统实现~Python+人工智能+TensorFlow+算法模型
|
11天前
|
机器学习/深度学习 数据采集 人工智能
探索机器学习:从理论到Python代码实践
【10月更文挑战第36天】本文将深入浅出地介绍机器学习的基本概念、主要算法及其在Python中的实现。我们将通过实际案例,展示如何使用scikit-learn库进行数据预处理、模型选择和参数调优。无论你是初学者还是有一定基础的开发者,都能从中获得启发和实践指导。
27 2
|
8天前
|
机器学习/深度学习 人工智能 TensorFlow
人工智能浪潮下的自我修养:从Python编程入门到深度学习实践
【10月更文挑战第39天】本文旨在为初学者提供一条清晰的道路,从Python基础语法的掌握到深度学习领域的探索。我们将通过简明扼要的语言和实际代码示例,引导读者逐步构建起对人工智能技术的理解和应用能力。文章不仅涵盖Python编程的基础,还将深入探讨深度学习的核心概念、工具和实战技巧,帮助读者在AI的浪潮中找到自己的位置。
下一篇
无影云桌面