将进程附加到列表(但不对其执行任何操作)会改变程序行为
Posted
技术标签:
【中文标题】将进程附加到列表(但不对其执行任何操作)会改变程序行为【英文标题】:Appending a process to a list (but doing nothing with it) alters program behaviour 【发布时间】:2011-12-22 19:32:36 【问题描述】:在下面的程序中,当我将进程附加到列表中时(看似毫无意义的事情),它会按预期运行。但是,如果我删除附加,进程析构函数会在它运行之前被多次调用。只有n
构造但(n)(n+1)/2
(其中n
是进程数)破坏。这让我相信每个进程都被复制到每个新进程中,然后立即销毁。也许这就是多处理模块的工作方式。这是有道理的,因为每个进程都是当前进程的一个分支。但是,附加到列表的意义是什么?为什么只是这样做会阻止这种行为?
这是测试和示例输出:
import multiprocessing
class _ProcSTOP:
pass
class Proc(multiprocessing.Process):
def __init__(self, q, s):
s.i += 1
self._i = s.i
self._q = q
print('constructing:', s.i)
super().__init__()
def run(self):
dat = self._q.get()
while not dat is _ProcSTOP:
self._q.task_done()
dat = self._q.get()
self._q.task_done()
print('returning: ', self._i)
def __del__(self):
print('destroying: ', self._i)
if __name__ == '__main__':
q = multiprocessing.JoinableQueue()
s = multiprocessing.Manager().Namespace()
s.i = 0
pool = []
for i in range(4):
p = Proc(q, s)
p.start()
pool.append(p) # This is the line to comment
for i in range(10000):
q.put(i)
q.join()
for i in range(4):
q.put(_ProcSTOP)
q.join()
print('== complete')
附加示例输出:
constructing: 1
constructing: 2
constructing: 3
constructing: 4
returning: 3
returning: 2
== complete
returning: 1
returning: 4
destroying: 4
destroying: 3
destroying: 2
destroying: 1
没有附加的示例输出:
constructing: 1
constructing: 2
constructing: 3
destroying: 1
constructing: 4
destroying: 1
destroying: 2
destroying: 3
destroying: 1
destroying: 2
returning: 1
returning: 4
returning: 2
== complete
returning: 3
destroying: 1
destroying: 3
destroying: 2
destroying: 4
【问题讨论】:
你认为它与垃圾收集有关吗?症状表明有必要保留对类实例的引用。 @Dave。那是个很好的观点。我怀疑你在正确的轨道上。 【参考方案1】:将对象添加到列表将防止它在子进程中被删除,因为在分叉后它将调用“os._exit()”而不是清除整个堆栈
相关代码在multiprocessing/forking.py(Popen的构造函数,在“p.start()”上调用)
self.pid = os.fork()
if self.pid == 0:
if 'random' in sys.modules:
import random
random.seed()
code = process_obj._bootstrap()
sys.stdout.flush()
sys.stderr.flush()
os._exit(code)
_bootstrap 在哪里设置新进程并调用“运行”(代码在 multiprocessing/process.py 中)
【讨论】:
以上是关于将进程附加到列表(但不对其执行任何操作)会改变程序行为的主要内容,如果未能解决你的问题,请参考以下文章