Python 未回收垃圾的循环引用对象
我有一个小的方便类,我在代码中经常使用它,它是:Python 未回收垃圾的循环引用对象,python,garbage-collection,Python,Garbage Collection,我有一个小的方便类,我在代码中经常使用它,它是: 类结构(dict): 定义初始(自我,**kwargs): 自述(自我,**夸尔格) self.\uuu dict\uu u=self 它的好处在于,您可以使用字典键语法或常用对象样式访问属性: myStructure=Structure(name=“myStructure”) 打印myStructure[“name”] 打印myStructure.name 今天,我注意到,我的应用程序内存消耗在一种我本以为会减少的情况下略有增加。在我看来,
类结构(dict):
定义初始(自我,**kwargs):
自述(自我,**夸尔格)
self.\uuu dict\uu u=self
它的好处在于,您可以使用字典键语法或常用对象样式访问属性:
myStructure=Structure(name=“myStructure”)
打印myStructure[“name”]
打印myStructure.name
今天,我注意到,我的应用程序内存消耗在一种我本以为会减少的情况下略有增加。在我看来,从结构类生成的实例并不是垃圾收集的。下面是一个小片段来说明这一点:
导入gc
班级结构(dict):
定义初始(自我,**kwargs):
自述(自我,**夸尔格)
self.\uuu dict\uu u=self
structures=[Structure(name=“_{0}.”格式(str(value)),用于范围(4096)中的值)
打印“结构名称:”,结构[16]。名称
打印“结构名称:”,结构[16][“名称”]
del结构
gc.collect()
打印“Structures count:”,len([gc.get_objects()中obj的obj,如果类型(obj)是Structure])
具有以下输出:
Structure name: __16
Structure name: __16
Structures count: 4096
Structure name: __16
Structure name: __16
Structures count: 4096
loading... line 5001, 5002 objs, 0.6 / 1.8 MiB read in 0.2s
loading... line 10002, 10003 objs, 1.1 / 1.8 MiB read in 0.3s
loading... line 15003, 15004 objs, 1.7 / 1.8 MiB read in 0.5s
loaded line 16405, 16406 objs, 1.8 / 1.8 MiB read in 0.5s
checked 1 / 16406 collapsed 0
checked 16405 / 16406 collapsed 157
compute parents 0 / 16249
compute parents 16248 / 16249
set parents 16248 / 16249
collapsed in 0.2s
Total 16249 objects, 58 types, Total size = 3.2MiB (3306183 bytes)
Index Count % Size % Cum Max Kind
0 4096 25 1212416 36 36 296 Structure
1 390 2 536976 16 52 49432 dict
2 5135 31 417550 12 65 12479 str
3 82 0 290976 8 74 12624 module
4 235 1 212440 6 80 904 type
5 947 5 121216 3 84 128 code
6 1008 6 120960 3 88 120 function
7 1048 6 83840 2 90 80 wrapper_descriptor
8 654 4 47088 1 92 72 builtin_function_or_method
9 562 3 40464 1 93 72 method_descriptor
10 517 3 37008 1 94 216 tuple
11 139 0 35832 1 95 2280 set
12 351 2 30888 0 96 88 weakref
13 186 1 23200 0 97 1664 list
14 63 0 21672 0 97 344 WeakSet
15 21 0 18984 0 98 904 ABCMeta
16 197 1 14184 0 98 72 member_descriptor
17 188 1 13536 0 99 72 getset_descriptor
18 284 1 6816 0 99 24 int
19 14 0 5296 0 99 2280 frozenset
[Structure(4312707312 296B 2refs 2par),
type(4298634592 904B 4refs 100par 'Structure')]
Structure name: __16
Structures count: 0
loading... line 5001, 5002 objs, 0.6 / 1.4 MiB read in 0.1s
loading... line 10002, 10003 objs, 1.1 / 1.4 MiB read in 0.3s
loaded line 12308, 12309 objs, 1.4 / 1.4 MiB read in 0.4s
checked 12 / 12309 collapsed 0
checked 12308 / 12309 collapsed 157
compute parents 0 / 12152
compute parents 12151 / 12152
set parents 12151 / 12152
collapsed in 0.1s
Total 12152 objects, 57 types, Total size = 2.0MiB (2093714 bytes)
Index Count % Size % Cum Max Kind
0 390 3 536976 25 25 49432 dict
1 5134 42 417497 19 45 12479 str
2 82 0 290976 13 59 12624 module
3 235 1 212440 10 69 904 type
4 947 7 121216 5 75 128 code
5 1008 8 120960 5 81 120 function
6 1048 8 83840 4 85 80 wrapper_descriptor
7 654 5 47088 2 87 72 builtin_function_or_method
8 562 4 40464 1 89 72 method_descriptor
9 517 4 37008 1 91 216 tuple
10 139 1 35832 1 92 2280 set
11 351 2 30888 1 94 88 weakref
12 186 1 23200 1 95 1664 list
13 63 0 21672 1 96 344 WeakSet
14 21 0 18984 0 97 904 ABCMeta
15 197 1 14184 0 98 72 member_descriptor
16 188 1 13536 0 98 72 getset_descriptor
17 284 2 6816 0 99 24 int
18 14 0 5296 0 99 2280 frozenset
19 22 0 2288 0 99 104 classobj
正如您所注意到的,结构实例数仍然是4096
我对创建方便的自我参考的行进行了评论:
导入gc
班级结构(dict):
定义初始(自我,**kwargs):
自述(自我,**夸尔格)
#self.\uuu dict\uu u=self
structures=[Structure(name=“_{0}.”格式(str(value)),用于范围(4096)中的值)
#打印“结构名称:”,结构[16]。名称
打印“结构名称:”,结构[16][“名称”]
del结构
gc.collect()
打印“Structures count:”,len([gc.get_objects()中obj的obj,如果类型(obj)是Structure])
既然删除了循环引用,那么输出就有意义了:
Structure name: __16
Structures count: 0
我进一步推动了测试,用以分析内存消耗:
导入gc
导入pprint
来自meliae进口扫描仪
从meliae进口装载机
班级结构(dict):
定义初始(自我,**kwargs):
自述(自我,**夸尔格)
self.\uuu dict\uu u=self
structures=[Structure(name=“_{0}.”格式(str(value)),用于范围(4096)中的值)
打印“结构名称:”,结构[16]。名称
打印“结构名称:”,结构[16][“名称”]
del结构
gc.collect()
打印“Structures count:”,len([gc.get_objects()中obj的obj,如果类型(obj)是Structure])
scanner.dump_所有对象(“Test_001.json”)
om=loader.load(“Test_001.json”)
summary=om.summary()
打印摘要
结构=om.get_all(“结构”)
如果结构:
pprint.pprint(结构[0].c)
生成以下输出:
Structure name: __16
Structure name: __16
Structures count: 4096
Structure name: __16
Structure name: __16
Structures count: 4096
loading... line 5001, 5002 objs, 0.6 / 1.8 MiB read in 0.2s
loading... line 10002, 10003 objs, 1.1 / 1.8 MiB read in 0.3s
loading... line 15003, 15004 objs, 1.7 / 1.8 MiB read in 0.5s
loaded line 16405, 16406 objs, 1.8 / 1.8 MiB read in 0.5s
checked 1 / 16406 collapsed 0
checked 16405 / 16406 collapsed 157
compute parents 0 / 16249
compute parents 16248 / 16249
set parents 16248 / 16249
collapsed in 0.2s
Total 16249 objects, 58 types, Total size = 3.2MiB (3306183 bytes)
Index Count % Size % Cum Max Kind
0 4096 25 1212416 36 36 296 Structure
1 390 2 536976 16 52 49432 dict
2 5135 31 417550 12 65 12479 str
3 82 0 290976 8 74 12624 module
4 235 1 212440 6 80 904 type
5 947 5 121216 3 84 128 code
6 1008 6 120960 3 88 120 function
7 1048 6 83840 2 90 80 wrapper_descriptor
8 654 4 47088 1 92 72 builtin_function_or_method
9 562 3 40464 1 93 72 method_descriptor
10 517 3 37008 1 94 216 tuple
11 139 0 35832 1 95 2280 set
12 351 2 30888 0 96 88 weakref
13 186 1 23200 0 97 1664 list
14 63 0 21672 0 97 344 WeakSet
15 21 0 18984 0 98 904 ABCMeta
16 197 1 14184 0 98 72 member_descriptor
17 188 1 13536 0 99 72 getset_descriptor
18 284 1 6816 0 99 24 int
19 14 0 5296 0 99 2280 frozenset
[Structure(4312707312 296B 2refs 2par),
type(4298634592 904B 4refs 100par 'Structure')]
Structure name: __16
Structures count: 0
loading... line 5001, 5002 objs, 0.6 / 1.4 MiB read in 0.1s
loading... line 10002, 10003 objs, 1.1 / 1.4 MiB read in 0.3s
loaded line 12308, 12309 objs, 1.4 / 1.4 MiB read in 0.4s
checked 12 / 12309 collapsed 0
checked 12308 / 12309 collapsed 157
compute parents 0 / 12152
compute parents 12151 / 12152
set parents 12151 / 12152
collapsed in 0.1s
Total 12152 objects, 57 types, Total size = 2.0MiB (2093714 bytes)
Index Count % Size % Cum Max Kind
0 390 3 536976 25 25 49432 dict
1 5134 42 417497 19 45 12479 str
2 82 0 290976 13 59 12624 module
3 235 1 212440 10 69 904 type
4 947 7 121216 5 75 128 code
5 1008 8 120960 5 81 120 function
6 1048 8 83840 4 85 80 wrapper_descriptor
7 654 5 47088 2 87 72 builtin_function_or_method
8 562 4 40464 1 89 72 method_descriptor
9 517 4 37008 1 91 216 tuple
10 139 1 35832 1 92 2280 set
11 351 2 30888 1 94 88 weakref
12 186 1 23200 1 95 1664 list
13 63 0 21672 1 96 344 WeakSet
14 21 0 18984 0 97 904 ABCMeta
15 197 1 14184 0 98 72 member_descriptor
16 188 1 13536 0 98 72 getset_descriptor
17 284 2 6816 0 99 24 int
18 14 0 5296 0 99 2280 frozenset
19 22 0 2288 0 99 104 classobj
内存使用率为3.2MiB,删除自参考线将导致以下输出:
Structure name: __16
Structure name: __16
Structures count: 4096
Structure name: __16
Structure name: __16
Structures count: 4096
loading... line 5001, 5002 objs, 0.6 / 1.8 MiB read in 0.2s
loading... line 10002, 10003 objs, 1.1 / 1.8 MiB read in 0.3s
loading... line 15003, 15004 objs, 1.7 / 1.8 MiB read in 0.5s
loaded line 16405, 16406 objs, 1.8 / 1.8 MiB read in 0.5s
checked 1 / 16406 collapsed 0
checked 16405 / 16406 collapsed 157
compute parents 0 / 16249
compute parents 16248 / 16249
set parents 16248 / 16249
collapsed in 0.2s
Total 16249 objects, 58 types, Total size = 3.2MiB (3306183 bytes)
Index Count % Size % Cum Max Kind
0 4096 25 1212416 36 36 296 Structure
1 390 2 536976 16 52 49432 dict
2 5135 31 417550 12 65 12479 str
3 82 0 290976 8 74 12624 module
4 235 1 212440 6 80 904 type
5 947 5 121216 3 84 128 code
6 1008 6 120960 3 88 120 function
7 1048 6 83840 2 90 80 wrapper_descriptor
8 654 4 47088 1 92 72 builtin_function_or_method
9 562 3 40464 1 93 72 method_descriptor
10 517 3 37008 1 94 216 tuple
11 139 0 35832 1 95 2280 set
12 351 2 30888 0 96 88 weakref
13 186 1 23200 0 97 1664 list
14 63 0 21672 0 97 344 WeakSet
15 21 0 18984 0 98 904 ABCMeta
16 197 1 14184 0 98 72 member_descriptor
17 188 1 13536 0 99 72 getset_descriptor
18 284 1 6816 0 99 24 int
19 14 0 5296 0 99 2280 frozenset
[Structure(4312707312 296B 2refs 2par),
type(4298634592 904B 4refs 100par 'Structure')]
Structure name: __16
Structures count: 0
loading... line 5001, 5002 objs, 0.6 / 1.4 MiB read in 0.1s
loading... line 10002, 10003 objs, 1.1 / 1.4 MiB read in 0.3s
loaded line 12308, 12309 objs, 1.4 / 1.4 MiB read in 0.4s
checked 12 / 12309 collapsed 0
checked 12308 / 12309 collapsed 157
compute parents 0 / 12152
compute parents 12151 / 12152
set parents 12151 / 12152
collapsed in 0.1s
Total 12152 objects, 57 types, Total size = 2.0MiB (2093714 bytes)
Index Count % Size % Cum Max Kind
0 390 3 536976 25 25 49432 dict
1 5134 42 417497 19 45 12479 str
2 82 0 290976 13 59 12624 module
3 235 1 212440 10 69 904 type
4 947 7 121216 5 75 128 code
5 1008 8 120960 5 81 120 function
6 1048 8 83840 4 85 80 wrapper_descriptor
7 654 5 47088 2 87 72 builtin_function_or_method
8 562 4 40464 1 89 72 method_descriptor
9 517 4 37008 1 91 216 tuple
10 139 1 35832 1 92 2280 set
11 351 2 30888 1 94 88 weakref
12 186 1 23200 1 95 1664 list
13 63 0 21672 1 96 344 WeakSet
14 21 0 18984 0 97 904 ABCMeta
15 197 1 14184 0 98 72 member_descriptor
16 188 1 13536 0 98 72 getset_descriptor
17 284 2 6816 0 99 24 int
18 14 0 5296 0 99 2280 frozenset
19 22 0 2288 0 99 104 classobj
确认结构实例已被销毁,内存使用率降至2.0MiB
你知道我如何确保这个类得到正确的垃圾收集吗?顺便说一下,所有这些都是在Python 2.7.2(Darwin)上执行的
干杯
Thomas通过使用
\uuuu getattr\uuuuu
和\uuuu setattr\uuuuu
允许属性访问到基础dict,可以更直接地实现结构类
class Structure(dict):
def __getattr__(self, k):
return self[k]
def __setattr__(self, k, v):
self[k] = v
周期在Python中是垃圾收集的,但只是周期性地收集(不像常规的引用计数对象,它们的引用计数一降到0就被收集)
避免循环(就像使用
\uuuu getattr\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu和\uuuuuuuuuuuu setattr\uuuuuuuuuuuuuuuuuuu。您可能想看看集合。namedtuple是一个很好的选择:它不完全是您实现的,但可能适合您的目的。您为什么想要这样的自引用?即使你坚持属性访问和项目查找的双重性(依我所知,这是个坏主意,根据Python的禅宗思想),也有更好、更少的方法来实现这一点。嗨,保罗,干杯!这看起来是个不错的选择,事实上我是从这篇文章中读到的。显然,垃圾收集bug也是众所周知的:关于namedTuple:我很久以前就已经看过了,但是我需要我的数据是可变的。