逆天的python项目分析工具【分析langchain】

DayNightStudy

共 8681字,需浏览 18分钟

 ·

2023-09-13 02:56

作者:aC大

原文转载:https://zhuanlan.zhihu.com/p/639056301

前言

之前的文章和视频对autoGPT的源码进行了剖析,有网友就问到,在分析autoGPT源码的时候画的模块图是用什么工具画的,有的甚至直接私信我直接要了模块关系图。应广大网友的要求,这次就分享一下这个逆天的python项目分析工具。


autoGPT的模块图示例


python项目分析的工具有哪些

有个网友对python 程序分析工具进行了比较系统的调研,里边有很多的工具及使用的场景和优缺点对比,具体对比如下:


工具 描述 开发语言 是否开源
PySonar2 语义索引器,用于批量处理大型代码库。牺牲实时索引能力,使用过程间分析来推断变量、参数和函数的类型。目前作为大型代码索引服务的基础引擎,Sourcegraph 中也有使用该工具。 java
Sourcegraph 代码搜索和导航引擎,帮助阅读和理解大型项目的代码。目前支持 Go、Java、Python 等多种编程语言,能够以浏览器插件的形式提供在线代码阅读的功能。 Go、TypeScript
coala 使用配置文件检测和修复代码,可自定义规则和标准检查代码质量,扩展性强。支持 Python、Java、C/C++、JavaScript 等多种编程语言,支持作为编辑器插件使用。 python
vprof 性能分析工具,为 Python 程序的运行时间、内存使用情况等提供交互式可视化,不适用于大型代码的分析。 Python、JavaScript
Code2Flow 为动态语言生成生成调用图(Call Graph),目前支持 Python、JavaScript、Ruby、PHP。基础流程:AST -> 函数定义 -> 函数调用点 -> 连接点 ,主要是提供一个粗略的概览。缺点是没有定义的函数、不同命名空间相同名字的函数将被跳过等,因此并不适用于大型代码的分析。 Python、JavaScript
pydeps Python 模块依赖可视化,导出 .svg 或 .png 文件。只考虑导入的文件(模块必须安装),在 Python 字节码中查找导入操作码,同时支持外部模块的分析。 Python
pycallgraph* 为 Python 应用生成调用图(Call Graph),包括函数的调用次数、执行时间等信息,提供一定程度的性能分析功能。同时支持过滤函数,避免生成的图太大无法分析,默认导出 .png 文件。 Python
undebt* 执行大规模自动化代码重构,根据自定义模式对代码进行查找和替换,适用于任何语言。 Python
pyt* 基于理论基础的 Python Web 应用静态分析(控制流图、定点、数据流分析),能够检测 SSRF、SQL 注入、XSS、目录遍历等攻击,支持自定义源点和汇点、传播污点的函数。目前已停更,作者建议使用 Pyre 。 Python
Pyre (Facebook) 性能类型检查器,集成静态分析工具 Pysa(污点分析)Pysa 通过跟踪数据流实现安全检查,依赖类型注释,能够高速处理大型代码。 OCaml、Python
Bandit 构建 AST 并使用插件检查安全问题,最初在 OpenStack 安全项目中开发,后来被重新定位到 PyCQA。主要用于扫描危险函数,支持自定义漏洞测试和扩展插件。 Python
Sourcetrail 跨平台的源代码浏览器,支持 C/C++、Java、Python,提供搜索、代码、图形三个交互式视图。亮点是给出了源代码的结构,但只有符号名称。 C++、Java
radon 计算源代码的度量(metrics),包括 McCabe、Halstead、可维护性索引三种度量指标,支持在 coala 中使用。主要用于评估代码的复杂度。 Python
xenon 基于 radon 的监测工具,检查代码复杂性。可应用于 CI/CD,在每次提交代码时运行,根据自定义代码复杂性阈值返回成功或失败。 Python
jedi Python 静态分析工具,侧重于自动补全和跳转,通常作为编辑器的插件使用。 Python
mypy 静态类型检查器(PEP 484),能够对 Python 程序中的类型注释执行静态检查。 Python
pyright (Microsoft) 可用于大型 Python 源代码库的快速类型检查器,使用内置的类型存根进行类型推断,可以在监视模式下运行,支持增量更新。 TypeScript、Python
pytype (Google) 静态分析器,无需类型注释就能检查和推断 Python 代码的类型,也利用了类型存根(pyi 文件)。 Python
Vulture 查找 Python 程序中未使用的代码(死代码),存在漏报,并且隐式调用可能会被误报。支持设置最小置信度、白名单等功能,可以对单个文件或目录的 py 文件执行分析。 Python
PyCG 使用静态分析为 Python 代码生成调用图,支持高阶函数、类继承、导入的模块、嵌套定义。详见论文 ICSE 2021 paper Python
Wily 复杂性检查 Python
McCabe 复杂性检查 Python
it 代码检查工具/框架 Python
CodeQL 代码分析引擎 未知
Fortify SCA 静态代码审计工具 未知
Pylance (Microsoft) 基于 pyright 的 Python 代码静态分析工具 未知
DeepSource 支持多种语言的静态分析,个人免费 未知
Codacy 能够通过静态代码分析获得关于安全问题、代码覆盖率、代码重复率、代码复杂性的信息 未知


上述包含的工具较多,开源的都可以在github上找到,每个工具适用的场景也不同,具体还是要根据个人的需求选择,我是用来分析autoGPT的模块间调用关系,对比分析发现,pydeps比较适合我。

pydeps的使用(langchain项目分析)

pydeps在github上已经开源,参数如下:

usage: pydeps [-h] [--debug] [--config FILE] [--no-config] [--version] [-L LOG] [--find-package] [-v] [-o file] [-T FORMAT] [--display PROGRAM] [--noshow] [--show-deps]              [--show-raw-deps] [--deps-output DEPS_OUT] [--show-dot] [--dot-output DOT_OUT] [--nodot] [--no-output] [--show-cycles] [--debug-mf INT] [--noise-level INT]              [--max-bacon INT] [--max-module-depth INT] [--pylib] [--pylib-all] [--include-missing] [-x PATTERN [PATTERN ...]] [-xx MODULE [MODULE ...]]              [--only MODULE_PATH [MODULE_PATH ...]] [--externals] [--reverse] [--rankdir {TB,BT,LR,RL}] [--cluster] [--min-cluster-size INT] [--max-cluster-size INT]              [--keep-target-cluster] [--collapse-target-cluster] [--rmprefix PREFIX [PREFIX ...]] [--start-color INT]              fname

从官网的参数介绍来看,感觉跟没介绍一样,只能通过实际的摸索分析参数的作用(边猜边实验)。该工具的安装比较简单可自行参考官网说明。下面以分析langchain工具为例,结合实际的应用需求,介绍几个比较重要的参数。前期工作:

# 1. 使用conda,创建pydeps的环境# 2. 在该环境下安装pydeps: pip install pydeps# 3. 激活该环境:conda activate pydeps# 4. 下载langchain项目,cd到项目目录下: cd xx/langchain# 5. 在langchain目录下,创建.pydeps文件 (为了演示的方便,将参数配置在.pydeps), 也可以不使用配置文件,直接在命令行输入对应的参数# 5. 开始后续的工作(以windows环境为例)

.pydeps文件按.ini格式解析,默认值如下:

[pydeps]max_bacon = 2   # 排除距离超过 n 跳的节点(默认=2, 0 -> 无限)verbose = 0    # 信息输出pylib = False  # 是否包含 python std lib 模块
exclude = # 排除模块(不在途中话出) os re sys collections __future__
langchain的模块调用关系使用默认命令:(pydeps) E:\py_workspace\langchain>pydeps langchain/__init__.py -o langchain_init.pngT png -

得到的是14M,无法上传原图,这里放一个缩小的图,主要是看至的模块关系:

langchain/__init__.py入口的模块关系图


这个图是无法看的,增加max_module_depth=2, 控制从入口模块到其他模块的长度

[pydeps]
max_module_depth = 2

得到的图为,控制了入口模块到其他模块的调用长度,这个图就比较清晰了,但是还发现 包含了requtest、jinjia2和urllib3等模块,这些模块我们并不需要分析,:


控制模块调用长度的图

于是在配置文件中增加exclude信息:

[pydeps]max_bacon = 2verbose = 0pylib = Falsemax_module_depth = 2exclude =    os    re    sys    collections    __future__    requests   # 新增    urllib3    # 新增    jinja2     # 新增

得到的图,这下出来的模块关系图就是我们需要的了,如果对颜色不喜欢,可以增加start_color=0的参数,值从0-360, 默认是0:


去掉不关注的第三方包


其他重要参数的介绍


参数 描述 补充说明
--config FILE 指定配置文件的路径,演示是使用的是当前目录的.pydeps
--no-config 禁用配置文件, 就是说即使当前目录有.pydeps也不会读取,只使用命令行的参数
-o file 输出文件
-T 输出的格式(svg或png)
--display PROGRAM 展示svg和png的程序,一般不指定
--max-bacon INT 排除距离超过 n 跳的节点(默认=2, 0 -> 无限) 模块将from xx import a, 之间的模块层数,设置合适的值便于分析。
--pylib 是否包含 python std lib 模块
--pylib-all 是否包含 python 所有 std lib 模块(包括 C 模块)
--include-missing 包含未安装的模块(或在 sys.path 上找不到)
--only MODULE_PATH 只包含以 MODULE_PATH 开头的模块,可以提供多个路径 这个在分析某个模块的时候很有用
--rankdir 设置图形的方向,合法值为TB(默认,导入模块在导入模块之上)、BT(与TB相反的方向)、LR(从左到右)和RL(从右到左) 上面显示的图就是TB的,上下结构,读者可以改成LR试试看
--cluster 将外部依赖项绘制为单独的集群 将max-bacon以外的节点绘制成一个icon
--min-cluster-size INT 集群之前依赖项必须具有的最小节点数(默认=0) 在max-bacon以外的节点,如果子图节点小于该值,则不绘制为一个icon(全部展示)
--max-cluster-size INT 在集群折叠为单个节点之前依赖项可以拥有的最大节点数(默认=0) 将小于该值的绘制为一个子图,大于该值的绘制为一个icon
-x PATTERN, --exclude PATTERN 要跳过的输入文件(例如 foo.*),可以提供多种模式
--exclude-exact MODULE (简写 -xx MODULE)与 --exclude 相同,但需要完全匹配。-xx foo.bar 将排除 foo.bar,但不排除 foo.bar.blob
--rmprefix PREFIX 从节点的显示名称中删除 PREFIX(可以提供多个前缀) 这个在图美观的时候能用到,比如模块http://langchain.chatModel.xxx太长,可以指定将langchain前缀移除,只显示http://chatModel.xxx


配置较为完整的配置如下:

[pydeps]verbose = 0pylib = False   # 不显示python libmax_module_depth = 2  # 显示最长链路
min_cluster_size = 2max_cluster_size = 2start_color= 180 # 画图的颜色,指定其实颜色,可选值0-360
exclude_exact = # 去掉指定的模块 langchain.utilities langchain.utilsexclude = # 去掉以os,re等开头的模块 os re sys collections __future__ requests urllib3 jinja2

上述配置的图为:



总结

pydeps的工具可以将整个项目的模块调用关系展示出来,甚至将调用的外部模块也可以展示出来,但是这样的话会让整个图很大,不利于将重点放在当前项目,因为可以通过参数,将模块的粒度控制在一个比较合理的范围便于解读。上文通过分析langchain的入口模块,展示了从最复杂的14M(其实还可以画的更复杂)到最后只有三个模块的过程,配合参数的设定突出要分析的模块更加有利于项目的分析。也为下一步源码剖析提供更清晰的指导。

浏览 590
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报