python 使用多进程启动进程后进行垃圾回收
python garbage collection after start process using 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
似乎多进程已经准备好清理堆栈并接管所有异常handling.But父框架不再存在。但是为什么框架仍然存在于第一个代码示例中?显然它仍然持有 a
并且对象根本没有被释放。
有什么方法可以在 python 中执行这种 gc 吗?
非常感谢。
为什么要关闭文件?假设这是一个 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
.
,它会变得更加疯狂
"it enters the f function and the A instance a would no longer be reachable." 一般情况下是不正确的。首先,子工作函数在 returns 时退出进程的唯一原因是 multiprocessing
模块从确保退出的函数调用它。在一般情况下,分叉函数可以 return 并执行其父代码。因此,从 python 的角度来看,a
仍然可以访问。此外,您的工作人员可以调用一个本身涉及 a
的函数。 python 无法知道这一点。
python 在 fork 之后清理所有 "unreferencable" 对象的成本非常高。而且非常危险,因为这些对象可以通过多种方式改变系统。
我测试了 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
似乎多进程已经准备好清理堆栈并接管所有异常handling.But父框架不再存在。但是为什么框架仍然存在于第一个代码示例中?显然它仍然持有 a
并且对象根本没有被释放。
有什么方法可以在 python 中执行这种 gc 吗?
非常感谢。
为什么要关闭文件?假设这是一个 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
.
"it enters the f function and the A instance a would no longer be reachable." 一般情况下是不正确的。首先,子工作函数在 returns 时退出进程的唯一原因是 multiprocessing
模块从确保退出的函数调用它。在一般情况下,分叉函数可以 return 并执行其父代码。因此,从 python 的角度来看,a
仍然可以访问。此外,您的工作人员可以调用一个本身涉及 a
的函数。 python 无法知道这一点。
python 在 fork 之后清理所有 "unreferencable" 对象的成本非常高。而且非常危险,因为这些对象可以通过多种方式改变系统。