I test the gc behavior that python perform after start process using multiprocess:
from multiprocessing import Process
import time
class A(object):
def __del__(self):
print 'deleting'
def f(name):
import gc
gc.collect()
print 'hello', name
print [map(lambda s: str(s)[:64], gc.get_referrers(o)) for o in gc.get_objects() if isinstance(o, A)]
time.sleep(123)
def main():
a=A()
p = Process(target=f, args=('bob',))
p.start()
p.join()
if __name__ == '__main__':
try:
main()
except:
print 'sdfsdf!'
Output:
hello bob
[["[[], {'__setattr__': <slot wrapper '__setattr__' of 'object' obj", '<frame object at 0xb87570>', '<frame object at 0xbd7f80>']]
I want to close file descriptor by executing __del__
.
When the subprocess starts, it enters the f
function and the A
instance a
would no longer be reachable. But the __del__
is not executed so that means the a
object is still not freed. The output shows that it seems to be held by the frame object.
So I tried another way using Exception to clean the stack to try to free the unreachable object and execute __del__
function:
from multiprocessing import Process
import time
import sys
class GcHelp(Exception):
def __init__(self, func):
self.func = func
super(GcHelp, self).__init__(func.__name__)
class A(object):
def __del__(self):
print 'deleting'
def f():
print 'target function'
def raiser():
raise GcHelp(f)
def main():
a=A()
p = Process(target=raiser, args=())
p.start()
p.join()
if __name__ == '__main__':
try:
main()
except GcHelp as e:
sys.exc_clear()
e.func()
except:
print 'sdfsdf!'
Output:
Process Process-1:
Traceback (most recent call last):
File "/usr/lib64/python2.7/multiprocessing/process.py", line 258, in _bootstrap
self.run()
File "/usr/lib64/python2.7/multiprocessing/process.py", line 114, in run
self._target(*self._args, **self._kwargs)
File "gc1.py", line 19, in raiser
raise GcHelp(f)
GcHelp: f
It seems that the multiprocess have ready clean the stack and take over all exception handling.But parent frame does not exist any more. But why the frame is still there in the first code example? Obviously it still holding the a
and the object is not freed at all.
Is there some way to perform this kind of gc in python?
Thanks a lot.