-
Notifications
You must be signed in to change notification settings - Fork 0
/
garbage_collection.py
71 lines (56 loc) · 2.03 KB
/
garbage_collection.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# Explanations from http://www.digi.com/wiki/developer/index.php/Python_Garbage_Collection
# A part of the code also comes from there
"""
Deallocation of memory is done in Python via two things:
- ref counting
- garbage collection
Ref counting counts each reference to an object from the moment it is allocated. Once this number
reaches 0, the object is deallocated.
But sometimes, ref counting does not work, for instance when an object has a reference to itself,
of when two objects have reference to eah other, although they are not used anymore.
This is where garbage collection comes into the game, to find and destroy those objects
"""
import gc
def make_unreachable_object():
l = []
def make_unreachable_object_with_ref_cycles():
l=[]
l.append(l)
return l
def make_uncollectable_object():
class Child:
def __init__(self, parent):
self.parent = parent
def __del__(self):
self.parent = None
class Parent:
def makeChild(self):
self.child = Child(self)
def __del__(self):
self.child = None
p=Parent()
p.makeChild()
def main():
print "\tCreating 1 unreachable object => should be destroyed automatically"
make_unreachable_object()
print "\tCollect...=> no unreachable or uncollectable should be visible"
collected = gc.collect(0)
assert(collected == 0)
assert(gc.garbage == [])
print "\tCreating 1 unreachable object with ref cycles"
make_unreachable_object_with_ref_cycles()
print "\tCollect...=> 1 unreachable and 0 uncollectable should be visible"
collected = gc.collect(0)
assert(collected == 1)
assert(gc.garbage == [])
print "\tCreating 1 uncollectable object"
make_uncollectable_object()
print "\tCollect...=> Unreachables and uncollectables should be visible"
collected = gc.collect(0)
assert(collected != 0)
assert(gc.garbage != [])
if __name__ == "__main__":
gc.disable() # disable automatic garbage collection
gc.set_debug(gc.DEBUG_STATS | gc.DEBUG_COLLECTABLE | gc.DEBUG_UNCOLLECTABLE | gc.DEBUG_INSTANCES | gc.DEBUG_OBJECTS) # activate gc debug flags
main()
gc.set_debug(0) # deactivate gc debug flags