[ 英语 | 中文]
ObjWatch 是一个强大的 Python 库,旨在简化复杂项目的调试和监控。通过提供对象属性和方法调用的实时跟踪,ObjWatch 使开发人员能够更深入地了解其代码库,从而促进问题识别、性能优化和整体代码质量增强。
ObjWatch 可能会影响您的应用程序的性能。建议仅在调试环境中使用它。
嵌套结构跟踪:通过清晰的分层日志记录可视化和监控嵌套函数调用和对象交互。
增强的日志记录支持:利用 Python 的内置日志记录模块进行结构化、可定制的日志输出,包括对简单和详细格式的支持。此外,为了确保即使记录器被外部库禁用或删除也能捕获日志,您可以设置 level="force"。当 level 设置为“force”时,ObjWatch 会绕过标准日志处理程序并使用 print() 来…
在读取和调试复杂项目时,经常会遇到多达十几层的嵌套调用,导致难以确定执行顺序。最令人沮丧的方面是在多进程环境中进行调试;调试单个进程常常会导致其他进程等待并超时,需要不断重新启动调试程序。频繁使用print语句会导致错过函数调用,费时费力。目前还没有一个兼具简单性和全面性的调试库,所以我花了一个周末开发了一个工具来解决这个痛点。
ObjWatch 专为简化复杂项目的调试和监控而设计。它提供对象属性和方法调用的实时跟踪,并允许自定义挂钩来帮助开发人员更深入地了解代码库。
您可以直接使用 pip install objwatch 安装它。为了演示目的,您需要克隆源代码:
git clone https://github.com/aeeeeeep/objwatch cd objwatch pip install . python3 examples/example_usage.py
执行上述代码会产生以下调用信息:
[2025-01-04 19:15:13] [DEBUG] objwatch: Processed targets: >>>>>>>>>> examples/example_usage.py <<<<<<<<<< [2025-01-04 19:15:13] [WARNING] objwatch: wrapper 'BaseLogger' loaded [2025-01-04 19:15:13] [INFO] objwatch: Starting ObjWatch tracing. [2025-01-04 19:15:13] [INFO] objwatch: Starting tracing. [2025-01-04 19:15:13] [DEBUG] objwatch: run main <- [2025-01-04 19:15:13] [DEBUG] objwatch: | run SampleClass.__init__ <- '0':(type)SampleClass, '1':10 [2025-01-04 19:15:13] [DEBUG] objwatch: | end SampleClass.__init__ -> None [2025-01-04 19:15:13] [DEBUG] objwatch: | run SampleClass.increment <- '0':(type)SampleClass [2025-01-04 19:15:13] [DEBUG] objwatch: | | upd SampleClass.value None -> 10 [2025-01-04 19:15:13] [DEBUG] objwatch: | | upd SampleClass.value 10 -> 11 [2025-01-04 19:15:13] [DEBUG] objwatch: | end SampleClass.increment -> None [2025-01-04 19:15:13] [DEBUG] objwatch: | run SampleClass.increment <- '0':(type)SampleClass [2025-01-04 19:15:13] [DEBUG] objwatch: | | upd SampleClass.value 11 -> 12 [2025-01-04 19:15:13] [DEBUG] objwatch: | end SampleClass.increment -> None [2025-01-04 19:15:13] [DEBUG] objwatch: | run SampleClass.increment <- '0':(type)SampleClass [2025-01-04 19:15:13] [DEBUG] objwatch: | | upd SampleClass.value 12 -> 13 [2025-01-04 19:15:13] [DEBUG] objwatch: | end SampleClass.increment -> None [2025-01-04 19:15:13] [DEBUG] objwatch: | run SampleClass.increment <- '0':(type)SampleClass [2025-01-04 19:15:13] [DEBUG] objwatch: | | upd SampleClass.value 13 -> 14 [2025-01-04 19:15:13] [DEBUG] objwatch: | end SampleClass.increment -> None [2025-01-04 19:15:13] [DEBUG] objwatch: | run SampleClass.increment <- '0':(type)SampleClass [2025-01-04 19:15:13] [DEBUG] objwatch: | | upd SampleClass.value 14 -> 15 [2025-01-04 19:15:13] [DEBUG] objwatch: | end SampleClass.increment -> None [2025-01-04 19:15:13] [DEBUG] objwatch: | run SampleClass.decrement <- '0':(type)SampleClass [2025-01-04 19:15:13] [DEBUG] objwatch: | | upd SampleClass.value 15 -> 14 [2025-01-04 19:15:13] [DEBUG] objwatch: | end SampleClass.decrement -> None [2025-01-04 19:15:13] [DEBUG] objwatch: | run SampleClass.decrement <- '0':(type)SampleClass [2025-01-04 19:15:13] [DEBUG] objwatch: | | upd SampleClass.value 14 -> 13 [2025-01-04 19:15:13] [DEBUG] objwatch: | end SampleClass.decrement -> None [2025-01-04 19:15:13] [DEBUG] objwatch: | run SampleClass.decrement <- '0':(type)SampleClass [2025-01-04 19:15:13] [DEBUG] objwatch: | | upd SampleClass.value 13 -> 12 [2025-01-04 19:15:13] [DEBUG] objwatch: | end SampleClass.decrement -> None [2025-01-04 19:15:13] [DEBUG] objwatch: end main -> None [2025-01-04 19:15:13] [INFO] objwatch: Stopping ObjWatch tracing. [2025-01-04 19:15:13] [INFO] objwatch: Stopping tracing.
代码中最关键的部分如下:
# Using as a Context Manager with Detailed Logging with objwatch.ObjWatch(['examples/example_usage.py']): main() # Using the API with Simple Logging obj_watch = objwatch.watch(['examples/example_usage.py']) main() obj_watch.stop()
我们可以通过上下文管理器和 API 调用来使用该工具。在示例中,我们指定对examples/example_usage.py 文件进行跟踪,这意味着该工具将记录examples/example_usage.py 中的任何函数、方法或变量。这种清晰的分层日志记录有助于可视化和监视嵌套函数调用和对象交互。打印的日志包括以下几种执行类型:
示例相对简单,但此功能对于执行大型项目非常有用。
ObjWatch 提供以下接口:
ObjWatch 提供了 FunctionWrapper 抽象基类,允许用户创建自定义包装器来扩展和自定义库的跟踪和日志记录功能。通过继承FunctionWrapper,开发人员可以实现针对特定项目需求的定制行为。这些行为会在函数调用和返回时执行,提供更专业的监控。
FunctionWrapper 类定义了两个必须实现的核心方法:
该方法在函数调用开始时被调用。它接收函数名称和当前帧对象,其中包含执行上下文,包括局部变量和调用堆栈。实现此方法以在函数执行之前提取、记录或修改信息。
此方法在函数返回时调用。它接收函数名称和函数返回的结果。使用此方法在函数完成执行后记录、分析或更改信息。
当变量更新时会触发该方法,接收旧值和当前值。它可用于记录变量的更改,从而允许跟踪和调试变量状态转换。
有关框架对象的更多详细信息,请参阅Python官方文档。
这是我根据我的使用场景实现的自定义包装器的示例。代码位于 objwatch/wrappers.py 文件中。该包装器自动记录指定模块内所有函数方法调用中输入和输出的张量形状以及变量的状态。这对于理解复杂分布式框架的执行逻辑非常有用。
git clone https://github.com/aeeeeeep/objwatch cd objwatch pip install . python3 examples/example_usage.py
在深度学习项目中,张量的形状和维度至关重要。小尺寸误差可能会导致整个模型无法正确训练或预测。手动检查每个张量的形状既乏味又容易出错。 TensorShapeLogger 自动记录张量形状,帮助开发人员:
建议参考tests/test_torch_train.py文件。该文件包含 PyTorch 训练过程的完整示例,演示如何集成 ObjWatch 进行监控和日志记录。
⚠️ 性能警告
在调试环境中使用 ObjWatch 会影响程序的性能。因此,建议仅在调试和开发阶段使用它。
这只是初步的写作;我计划随着时间的推移添加更多。如果您觉得有用,请随意给它一个star。
该库仍在积极更新中。如果您有任何问题或建议,请发表评论或在存储库中打开问题。
以上是调试救星!利用 ObjWatch 在复杂的 Python 项目中进行高效的代码理解和调试的详细内容。更多信息请关注PHP中文网其他相关文章!