Python pympler 库2025 年 3 月 17 日 | 阅读 26 分钟 像 Python 这样的编程语言包含不同的库集来执行内存分析。这些库的例子可以是 memory_profiler、guppy/heapy、scalene 等。所有这些库都通过 Python 代码以多种方式提供内存使用。但是,它们都没有提供监视使用用户定义类创建的对象的内存利用率的功能。在某些情况下,我们需要监视特定类型对象的内存使用情况。一个名为 pympler 的 Python 库对于这些需求非常有用。pympler 库包含一个模块列表,允许我们以不同的方式通过 Python 脚本监视内存利用率。在下面的教程中,我们将借助各种示例了解 pympler 库中可用的不同模块。 那么,让我们开始吧。 理解 Python pympler 库pympler 库是一个开发工具,用于测量、监视和分析正在运行的基于 Python 的应用程序中 Python 对象的内存行为。 我们可以通过对 Python 应用程序进行 pympling 来详细了解 Python 对象的大小和生命周期。我们还可以轻松识别不理想或意外的运行时行为,例如内存膨胀和其他“pymples”。 Pympler 将三个以前独立的模块集成到一个全面、强大的分析实用程序中。asizeof 模块提供了一个或多个 Python 对象的基本大小详细信息。muppy 模块用于 Python 应用程序的在线监视。ClassTracker 类提供了对选定 Python 对象生命周期的离线分析。 一个 Web 分析前端公开了进程统计信息、垃圾可视化和类跟踪器统计信息。 pympler 库的要求pympler 库完全用 Python 编写,不依赖任何外部库。该库集成了 Bottle 和 Flot。Pympler 库已在 Python 3.5、3.6、3.7、3.8、3.9 和 3.10 上进行测试。 Pympler 是一个平台独立的库,已在不同的 Linux 发行版(32 位和 64 位)、Windows 7 和 MacOS X 上进行测试。 如何安装 Python pympler 库?为了安装 Python 库,我们需要 'pip',这是一个用于管理从受信任的公共仓库安装模块所需的包的框架。一旦我们有了 'pip',我们就可以使用 Windows 命令提示符 (CMD) 或终端中的命令安装 pympler 库,如下所示 语法 验证安装模块安装完成后,我们可以通过创建一个空的 Python 程序文件并写入如下 import 语句来验证它: 文件:verify.py 现在,保存上述文件并在终端中使用以下命令执行它: 语法 如果上述 Python 程序文件没有返回任何错误,则说明库已正确安装。但是,如果出现异常,请尝试重新安装库,建议也查阅 pympler 库的官方文档。 在下面的教程中,我们将介绍以下模块列表
让我们详细了解 pympler 库的这些模块。 理解 asizeof 模块asizeof 模块允许我们使用它提供的不同方法测量对象的大小。 其中一些方法在下表中描述
让我们看一些示例,演示 asizeof 模块上述方法的用法。 示例 1输出 Size of the List list1: 880 bytes Size of the List list2: 48 bytes Size of the List list1, list2 combined: 928 bytes Size of the List list1 & list2: 880 bytes, 48 bytes 说明 在上述代码片段中,我们从 pympler 库中导入了 asizeof 模块。然后我们定义了两个不同的列表。然后我们使用 asizeof() 和 asizesof() 方法来计算不同列表的大小并向用户打印结果。 示例 2输出 Object Type: 说明 在上述代码片段中,我们再次导入了所需的模块并定义了两个不同的列表。然后我们定义了一个对象,该对象存储从 asized() 函数生成的列表。然后我们打印了对象的类型以及对象。然后我们使用 flat 和 size 属性返回对象的平面大小和总大小。然后我们再次使用 asized() 方法包含两个列表。然后我们打印了两个列表的格式。最后,我们打印了对象统计信息和详细信息。 示例 3输出 Size of Single element in a List : 8 bytes Basic Size of Object : 72 bytes Flat Size of Object : 248 bytes List of Objects Referred by an Object : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 说明 在上述代码片段中,我们使用了 itemsize()、basicsize()、flatsize() 和 refs() 等方法来打印与我们定义的列表相关的不同详细信息。 示例 4输出 Is Object Class : False Is Object Built-in : False Is Object Code : False Is Object Frame : False Is Object Function : False Is Object method : False Is Object Module : False Is Object Module : True Is Object Function : False Is Object method : True Is Object Function : True Is Object method : False Is Object Class : True Is Object Built-in : True Is Object Built-in : True Is Object Built-in : True 说明 我们已经导入了所需的模块并在上述代码片段中定义了列表。然后我们使用了 isclass()、isbuiltin()、iscode()、isframe()、isfunction()、ismethod() 和 ismodule() 等不同方法来打印不同的布尔输出。 理解 classtracker 和 classtracker_stats 模块classtracker 模块允许我们使用不同的方法监视用户定义类创建的对象的内存利用率。 classtracker_stats 模块允许我们以各种方式格式化借助 classtracker 模块捕获的数据。 在以下部分中,我们将通过不同的示例了解如何使用 classtracker 和 classtracker_stats 模块跟踪特定类型的用户定义对象的内存利用率,然后以多种方式格式化监视统计信息。 这些模块提供了各种类和方法。其中一些描述如下
现在让我们看一些示例,演示 classtracker 模块上述类和方法的用法。 示例 1输出 ---- SUMMARY ------------------------------------------------------------------ Start active 0 B average pct RandomNumberGenerator 0 64 B 0 B 0% Intermediate active 0 B average pct RandomNumberGenerator 2 25.75 MB 12.88 MB 0% End active 0 B average pct RandomNumberGenerator 2 17.17 MB 8.58 MB 0% ------------------------------------------------------------------------------- 说明 在上述代码片段中,我们导入了所需的模块。然后我们定义了一个类来生成随机数。我们创建了 ClassTracker() 类的一个对象,并使用 track_class() 方法跟踪创建的类。然后我们使用 create_snapshot() 方法记录注册类使用的内存。我们创建了该类的多个对象,并再次使用 create_snapshot() 方法。我们删除了该类的一个对象,并再次使用 create_snapshot() 方法。最后,我们使用 stats.print_summary() 方法打印了摘要,并使用 close() 方法关闭了处理。 示例 2输出 ---- SUMMARY ------------------------------------------------------------------ Start active 0 B average pct RandDistribution 0 0 B 0 B 0% RandomNumberGenerator 0 64 B 0 B 0% Intermediate active 0 B average pct RandDistribution 2 156.84 KB 78.42 KB 0% RandomNumberGenerator 2 7.63 MB 3.81 MB 0% End active 0 B average pct RandDistribution 1 78.45 KB 78.45 KB 0% RandomNumberGenerator 1 3.82 MB 3.82 MB 0% ------------------------------------------------------------------------------- ---- SUMMARY ------------------------------------------------------------------ ------------------------------------------------------------------------------- 说明 在上述代码片段中,我们再次导入了所需的模块并创建了两个不同的类。我们创建了 ClassTracker() 类的一个对象,并对两个类都使用了 track_class() 方法。然后我们多次使用 create_snapshot() 方法记录两个类使用的内存。我们还执行了不同的功能,例如实例化类、删除对象。然后我们打印了摘要。我们使用了 clear() 方法清除收集到的统计信息。最后,我们再次打印了摘要并关闭了进程。 示例 3输出 ---- SUMMARY ------------------------------------------------------------------ Start active 0 B average pct RandDistribution 0 352.16 KB 0 B 0% RandomNumberGenerator 0 88.22 KB 0 B 0% Intermediate active 0 B average pct RandDistribution 0 352.16 KB 0 B 0% RandomNumberGenerator 0 88.22 KB 0 B 0% End active 0 B average pct RandDistribution 0 352.16 KB 0 B 0% RandomNumberGenerator 0 88.22 KB 0 B 0% ------------------------------------------------------------------------------- 说明 在上述代码片段中,我们已经看到了 track_object() 和 track_change() 等方法的用法,以监视传递给它的对象以及对它的更改所使用的内存。 示例 4输出 ---- SUMMARY ------------------------------------------------------------------ Start active 0 B average pct RandDistribution 0 0 B 0 B 0% RandomNumberGenerator 0 64 B 0 B 0% Intermediate active 0 B average pct RandDistribution 0 176.11 KB 0 B 0% RandomNumberGenerator 1 8.58 MB 8.58 MB 0% End active 0 B average pct RandDistribution 0 176.11 KB 0 B 0% RandomNumberGenerator 1 8.58 MB 8.58 MB 0% ------------------------------------------------------------------------------- ---- SUMMARY ------------------------------------------------------------------ Start active 0 B average pct RandDistribution 0 0 B 0 B 0% RandomNumberGenerator 0 64 B 0 B 0% Intermediate active 0 B average pct RandDistribution 0 176.11 KB 0 B 0% RandomNumberGenerator 1 8.58 MB 8.58 MB 0% End active 0 B average pct RandDistribution 0 176.11 KB 0 B 0% RandomNumberGenerator 1 8.58 MB 8.58 MB 0% Last active 0 B average pct RandDistribution 1 176.11 KB 176.11 KB 0% RandomNumberGenerator 0 16 B 0 B 0% ------------------------------------------------------------------------------- Tracked Classes : ['RandDistribution', 'RandomNumberGenerator'] 说明 在上述代码片段中,我们演示了删除我们不想监视的类的方法以及将监视统计信息转储到输出文件的方法,我们以后可以加载该文件。对于此示例,我们使用了 detach_class()、stats.sort_stats() 和 stats.dump_stats() 方法。首先,我们注册了我们之前创建的两个类进行监视,然后创建了类的实例,删除了几个实例,然后从监视中注销了一个类。我们还在步骤之间拍摄了内存快照。然后我们检查它是否仍在监视正在创建的该类的新对象。最后,我们将监视统计信息存储在输出文件中。 classtracker 模块还提供了一个 ConsoleStats 类,它允许我们从文件加载监视统计信息。下面我们重新加载了上一步中存储到文件的监视统计信息并再次打印统计信息以进行验证。 示例 5输出 ---- SUMMARY ------------------------------------------------------------------ Start active 0 B average pct RandDistribution 0 0 B 0 B 0% RandomNumberGenerator 0 64 B 0 B 0% Intermediate active 0 B average pct RandDistribution 0 176.11 KB 0 B 0% RandomNumberGenerator 1 8.58 MB 8.58 MB 0% End active 0 B average pct RandDistribution 0 176.11 KB 0 B 0% RandomNumberGenerator 1 8.58 MB 8.58 MB 0% Last active 0 B average pct RandDistribution 1 176.11 KB 176.11 KB 0% RandomNumberGenerator 0 16 B 0 B 0% ------------------------------------------------------------------------------- Tracked Classes : ['RandDistribution', 'RandomNumberGenerator'] 说明 在上述代码片段中,我们使用了 ConsoleStats() 类并打印了摘要。 示例 6输出 ---- SUMMARY ------------------------------------------------------------------ Start active 0 B average pct RandDistribution 0 0 B 0 B 0% RandomNumberGenerator 0 64 B 0 B 0% Intermediate active 0 B average pct RandDistribution 2 352.16 KB 176.08 KB 0% RandomNumberGenerator 2 17.17 MB 8.58 MB 0% End active 0 B average pct RandDistribution 1 176.11 KB 176.11 KB 0% RandomNumberGenerator 1 8.58 MB 8.58 MB 0% ------------------------------------------------------------------------------- Tracked Classes : ['RandDistribution', 'RandomNumberGenerator'] HTML 输出 ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() 说明 在上述代码片段中,我们解释了如何使用 HtmlStats() 类将监视统计信息格式化为 HTML 文件,其中包含解释类内存使用情况的图表。然后我们使用 create_html() 方法创建了 HTML 文件。 示例 7输出 ---- SUMMARY ------------------------------------------------------------------ active 0 B average pct RandDistribution 0 0 B 0 B 0% RandomNumberGenerator 0 64 B 0 B 0% ------------------------------------------------------------------------------- ---- SUMMARY ------------------------------------------------------------------ active 0 B average pct RandDistribution 0 0 B 0 B 0% RandomNumberGenerator 0 64 B 0 B 0% ------------------------------------------------------------------------------- ---- SUMMARY ------------------------------------------------------------------ active 0 B average pct RandDistribution 0 0 B 0 B 0% RandomNumberGenerator 0 64 B 0 B 0% active 0 B average pct RandDistribution 2 352.16 KB 176.08 KB 0% RandomNumberGenerator 2 17.17 MB 8.58 MB 0% ------------------------------------------------------------------------------- 说明 在上述代码片段中,我们解释了如何使用 PeriodicThread() 类通知类跟踪器定期拍摄快照,而不是每次手动拍摄快照。在上面的示例中,我们演示了 tracker.stop_periodic_snapshots() 和 tracker.start_periodic_snapshots() 方法的用法。 理解 tracker 模块跟踪器模块允许我们监视随时间变化的总体内存使用情况。它允许我们跟踪摘要之间内存使用情况的差异。 我们将从从 pympler 库导入 tracker 模块开始 语法 以下是 tracker 模块提供的类和方法
让我们看一些示例,演示上述方法的用法。 示例 1输出 types | # objects | total size ========================================= | =========== | ============ list | 3871 | 334.62 KB str | 3875 | 270.01 KB int | 881 | 24.10 KB dict | 7 | 1.48 KB code | 1 | 1.22 KB tuple | 12 | 672 B pympler.asizeof.Asized | 8 | 512 B function (store_info) | 1 | 136 B pympler.process._ProcessMemoryInfoWin32 | 2 | 96 B pympler.classtracker.Snapshot | 2 | 96 B cell | 2 | 80 B weakref | 1 | 72 B method | 1 | 64 B float | 2 | 48 B 说明 在上述代码片段中,我们导入了所需的模块。然后我们创建了 SummaryTracker() 类的一个实例,并使用 print_diff() 方法打印了两个摘要之间的差异。 示例 2输出 types | # objects | total size ========================================= | =========== | ============ list | 3870 | 453.31 KB int | 15858 | 433.62 KB str | 3874 | 269.93 KB dict | 4 | 576 B pympler.asizeof.Asized | 8 | 512 B tuple | 8 | 448 B code | 0 | 179 B pympler.process._ProcessMemoryInfoWin32 | 2 | 96 B pympler.classtracker.Snapshot | 2 | 96 B float | 2 | 48 B 说明 在上述代码片段中,我们导入了所需的模块。然后我们创建了 SummaryTracker() 类的一个实例,并使用 create_summary() 方法创建了两个不同的摘要。然后我们使用 print_diff() 方法打印了两个内存使用摘要之间的差异。 示例 3输出 [ ['list', 3870, 464192], ['int', 15856, 443976], ['str', 3874, 276407], ['dict', 4, 576], ['pympler.asizeof.Asized', 8, 512], ['tuple', 8, 448], ['code', 0, 413], ['pympler.process._ProcessMemoryInfoWin32', 2, 96], ['pympler.classtracker.Snapshot', 2, 96], ['float', 2, 48] ] 说明 在上述代码片段中,我们使用了 diff() 方法返回两个摘要之间的差异作为列表,并使用 sorted() 方法对列表进行排序并打印给用户。 理解 muppy 模块muppy 模块允许开发人员检测内存泄漏。 我们将从从 pympler 库导入 muppy 模块开始 语法 muppy 模块提供的不同方法描述如下
让我们看以下示例,说明 muppy 模块上述方法的用法 示例 1输出 Number of Objects : 50880 说明 在上述代码片段中,我们导入了所需的模块,并使用 get_objects() 方法获取内存中所有对象的列表,并使用 len() 方法打印了对象的总数。 示例 2输出 [ [], [( 2294, 140, 'the_objects = muppy.get_objects()\nprint("Number of Objects : ", len(the_objects))', 'the_objects = muppy.get_objects()\nprint("Number of Objects : ", len(the_objects))' )], [], [], [] ] 说明 在上述代码片段中,我们使用了 filter() 方法过滤列表中的对象,并向用户打印了列表。 示例 3输出 Number of Objects Referred by List the_list : 5999 types | # objects | total size ============================ | =========== | ============ str | 15902 | 3.10 MB dict | 4296 | 1.67 MB code | 5352 | 924.66 KB type | 836 | 654.47 KB list | 318 | 563.39 KB int | 7640 | 213.69 KB set | 146 | 213.30 KB tuple | 3411 | 194.41 KB wrapper_descriptor | 2201 | 154.76 KB method_descriptor | 1239 | 87.12 KB abc.ABCMeta | 87 | 85.15 KB builtin_function_or_method | 1210 | 85.08 KB weakref | 1177 | 82.76 KB getset_descriptor | 849 | 53.06 KB frozenset | 122 | 47.48 KB Size of List theList : 121432 bytes 说明 在上述代码片段中,我们演示了 get_referents()、print_summary() 和 getsizeof() 方法的用法。 理解 garbagegraph 模块garbagegraph 模块允许我们监视循环对象。此模块包含一个名为 GarbageGraph 的类,它接受一个对象输入列表,并生成 graphviz 可视化,显示它们之间的关系,这可以帮助我们检测循环。GarbageGraph 是 ReferenceGraph 的扩展,我们将在 refgraph 部分讨论它。 我们将从从 pympler 库导入 garbagegraph 模块开始 语法 以下是 garbagegraph 模块提供的方法
现在让我们看一个示例,演示 garbagegraph 模块上述方法的用法。 示例输出文件:refGraph.out // Process this file with graphviz digraph G { node [shape=box]; "Xx7f39954b7340" [ label = "'A'\nstr" ]; "Xx55ca999273e0" [ label = "True\nbool" ]; "Xx7f38d1955cf0" [ label = "{'A': True}\ndict" ]; "Xx7f38d0ab2508" [ label = "[10, 20, 30]\nlist" ]; "Xx7f38d1404b88" [ label = "{20 : 30}\ndict" ]; Xx7f38d1955cf0 -> Xx55ca999273e0 [label="A"]; } 输出 True 说明 在上述代码片段中,我们演示了 garbagegraph 模块的 write_graph() 和 render() 方法的用法。 理解 refbrowser 模块refbrowser 模块允许我们打印对象引用者的树状图。 我们将从从 pympler 库导入 refbrowser 模块开始 语法 让我们看以下示例,演示 refbrowser 模块的 ConsoleBrowser 和 FileBrowser 类的用法。 示例 1输出 Using the ConsoleBrowser Class: str-+-list--dict--module(__main__) +-dict--module(__main__)--dict +-frozenset--dict-+-module(sre_parse) | +-function (_class_escape) | +-function (_escape) | +-function (_uniq) | +-function (_parse_sub) | +-function (_parse) | +-function (_parse_flags) | +-function (fix_flags) | +-function (parse) | +-function (parse_template) | +-function (expand_template) | +-function (__init__) | +-function (opengroup) | +-function (closegroup) | +-function (checkgroup) | +-function (checklookbehindgroup) | +-function (__init__) | +-function (dump) | +-function (__repr__) | +-function (__len__) | +-function (__delitem__) | +-function (__getitem__) | +-function (__setitem__) | +-function (insert) | +-function (append) | +-function (getwidth) | +-function (__init__) | +-function (__next) | +-function (match) | +-function (get) | +-function (getwhile) | +-function (getuntil) | +-function (tell) | +-function (seek) | +-function (error) | +-function (groups) | +-function (pos) 说明 从上面的示例中,我们可以了解如何借助 refbrowser 模块的 ConsoleBrowser 类创建对象的树状探索。 示例 2 输出 Using the FileBrowser Class: str-+-frame (codename: _get_tree)-+-frame (codename: _get_tree)-+-frame (codename: _get_tree) | | +-list | | | +-frame (codename: _get_tree)-+-frame (codename: _get_tree) | | +-list | | | +-frame (codename: _get_tree)-+-frame (codename: _get_tree) | | +-list | | +-list | | | +-frame (codename: _get_tree)-+-frame (codename: _get_tree) | | +-list | | | +-frame (codename: _get_tree)-+-frame (codename: _get_tree) | | +-list | | | +-list | +-frame (codename: _get_tree)-+-list | | +-frame (codename: _get_tree) | | +-list | | | +-frame (codename: _get_tree)-+-list | | +-frame (codename: _get_tree) | | | +-frame (codename: _get_tree)-+-list | | +-frame (codename: _get_tree) | | | +-frame (codename: _get_tree)--list | +-list-+-list-+-list | | +-list | | +-list | | +-list | | +-list | | +-list | | +-frame (codename: _get_tree) | | +-list | | +-list | | +-list | | +-list | | +-list | | +-frame (codename: _get_tree) | | | +-frame (codename: _get_tree)-+-list | | +-frame (codename: _get_tree) | | +-list | | | +-dict-+-list | +-list | +-frame (codename: _get_tree) | +-frame (codename: _get_tree) | +-frame (codename: _get_tree) | +-module(__main__) 说明 从上面的示例中,我们可以了解如何借助 refbrowser 模块的 FileBrowser 类创建对象的树状探索。 理解 refgraph 模块refgraph 模块允许我们创建引用的 graphviz 图。 我们将从从 pympler 库导入 refgraph 模块开始 语法 以下是 refgraph 模块提供的方法
现在让我们看一些示例,演示 refgraph 模块上述方法的用法。 示例 1输出 // Process this file with graphviz digraph G { node [shape=box]; "Xx238d66c43f0" [ label = "'A'\nstr" ]; "Xx7ffb66896868" [ label = "True\nbool" ]; "Xx238d6665b40" [ label = "{'A': True}\ndict" ]; "Xx238e53935c0" [ label = "[10, 20, 30]\nlist" ]; "Xx238d6665c00" [ label = "{20: 30}\ndict" ]; Xx238d6665b40 -> Xx7ffb66896868 [label="A"]; } 说明 在上述代码片段中,我们导入了所需的模块并定义了一些对象。然后我们创建了 ReferenceGraph() 类的一个对象,该对象接受之前定义的对象列表。然后我们使用 write_graph() 方法将引用图保存到输出文件。 示例 2输出 True 说明 在上述代码片段中,我们演示了 ReferenceGraph() 类的 render() 方法的用法。 理解 summary 模块summary 模块允许我们创建对象列表的摘要。 我们将从从 pympler 库导入 summary 模块开始 语法 以下是 summary 模块提供的方法
现在让我们看一个示例,演示 summary 模块上述方法的用法。 示例 1输出 types | # objects | total size ======= | =========== | ============ list | 345 | 79.32 KB 说明 在上述代码片段中,我们导入了所需的模块。然后我们使用了 summarize() 方法创建了对象列表的摘要作为表格。然后我们使用了 print_() 方法打印了 summarize() 方法的输出。 示例 2输出 types | # objects | total size ======= | =========== | ============ int | 5999 | 164.03 KB 说明 在上述代码片段中,我们导入了所需的模块。然后我们使用了 summarize() 方法创建了对象列表的摘要作为表格。然后我们使用了 print_() 方法打印了 summarize() 方法的输出。 示例 3输出 types | # objects | total size ============================ | =========== | ============ str | 16673 | 3.21 MB dict | 4544 | 1.77 MB code | 5638 | 975.36 KB type | 891 | 703.47 KB set | 147 | 213.51 KB tuple | 3615 | 205.41 KB wrapper_descriptor | 2294 | 161.30 KB builtin_function_or_method | 1486 | 104.48 KB method_descriptor | 1306 | 91.83 KB weakref | 1242 | 87.33 KB abc.ABCMeta | 87 | 85.15 KB list | 342 | 79.16 KB getset_descriptor | 901 | 56.31 KB int | 1814 | 54.70 KB frozenset | 122 | 47.48 KB 说明 在上述代码片段中,我们导入了所需的模块。然后我们使用了 summarize() 方法创建了对象列表的摘要作为表格。然后我们使用了 print_() 方法打印了 summarize() 方法的输出。 示例 4输出 types | # objects | total size ============================ | =========== | ============ str | 16671 | 3.21 MB dict | 4542 | 1.77 MB code | 5638 | 975.36 KB type | 891 | 703.47 KB set | 147 | 213.51 KB tuple | 3611 | 205.20 KB wrapper_descriptor | 2294 | 161.30 KB builtin_function_or_method | 1486 | 104.48 KB method_descriptor | 1306 | 91.83 KB weakref | 1242 | 87.33 KB abc.ABCMeta | 87 | 85.15 KB getset_descriptor | 901 | 56.31 KB int | 1804 | 54.42 KB frozenset | 122 | 47.48 KB function (__init__) | 253 | 33.60 KB 说明 在上述代码片段中,我们演示了 summary 模块的 get_diff() 方法的用法。 |
我们请求您订阅我们的新闻通讯以获取最新更新。