我使用multiprocess测试python在启动过程后执行的gc行为:
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!'
输出:
hello bob
[["[[], {'__setattr__': <slot wrapper '__setattr__' of 'object' obj", '<frame object at 0xb87570>', '<frame object at 0xbd7f80>']]
我想通过执行__del__
来关闭文件描述符。
子进程启动时,它会进入f
函数,A
实例a
将无法再访问。但是__del__
没有被执行,这意味着a
对象仍然没有被释放。输出显示它似乎由框架对象保持。
所以我尝试了另一种方法,使用Exception清理堆栈以尝试释放无法访问的对象并执行__del__
函数:
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!'
输出:
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
似乎多进程已经准备好清理堆栈并接管所有异常处理。但是父帧不再存在。但是为什么第一个代码示例中的帧仍然存在?显然它仍然保持a
并且对象根本没有被释放。
有没有办法在python中执行这种gc?
非常感谢。
答案 0 :(得分:0)
为什么要关闭文件?假设这是一个linuxy系统,分叉的环境就好了。如果关闭子文件中的文件,它将刷新仍在缓冲区中的所有数据......但是同一数据将在父项中再次刷新,从而导致重复数据。
import multiprocessing as mp
fd = None
def worker():
# child closes file, flushing "1"
fd.close()
def doit():
global fd
fd = open('deleteme', 'w')
fd.write('1')
p = mp.Process(target=worker)
p.start()
p.join()
# parent closes file, flushing "1"
fd.close()
# lets see what we got
print(open('deleteme').read())
doit()
此脚本打印11
,因为子文件对象和父文件对象都写入了1
。如果任何一方调用flush
或seek
,那就会变得更加疯狂。
&#34;它进入f函数,A实例a将无法再访问。&#34; 一般来说,这不是真的。首先,子worker函数返回时退出进程的唯一原因是multiprocessing
模块从确保退出的函数调用它。在一般情况下,分叉函数可以返回并执行其父代码。因此,从python的角度来看,a
仍然可以访问。此外,您的工作人员可以调用自己触及a
的函数。 python无法知道这一点。
python清理所有&#34;不可接受的&#34;将会非常昂贵。叉子后的对象。并且非常危险,因为这些对象可以在很多方面改变系统。