Python 使用“事件”的多处理暂停重启功能`

Python 使用“事件”的多处理暂停重启功能`,python,multiprocessing,Python,Multiprocessing,我正在使用下面发布的代码来启用多处理池的暂停重启功能 如果您能解释一下为什么必须将事件变量作为参数发送给设置()函数,我将不胜感激。为什么在setup()函数的作用域内声明了一个全局变量unpaused,然后将其设置为与事件变量相同: def setup(event): global unpaused unpaused = event 我还想知道以下声明背后的逻辑: pool=mp.Pool(2, setup, (event,)) 提交的第一个参数是池要使用的CPU内核数。

我正在使用下面发布的代码来启用
多处理
池的暂停重启功能

如果您能解释一下为什么必须将
事件
变量作为参数发送给
设置()
函数,我将不胜感激。为什么在
setup()
函数的作用域内声明了一个全局变量
unpaused
,然后将其设置为与
事件
变量相同:

def setup(event):
    global unpaused
    unpaused = event
我还想知道以下声明背后的逻辑:

pool=mp.Pool(2, setup, (event,))
提交的第一个参数是池要使用的CPU内核数。 提交的第二个参数是上面提到的函数
setup()

为什么不能像这样完成这一切:

global event
event=mp.Event()
pool = mp.Pool(processes=2)
每次需要暂停或重新启动作业时,我们只需使用:

暂停:

event.clear()
要重新启动:

event.set()
为什么我们需要一个全局变量
非伪
?我不明白!请告知



您误解了
事件的工作原理。但首先,我将介绍
setup
正在做什么

setup
函数在池中的每个子进程启动后立即执行。因此,您正在将每个进程中名为
event
的全局变量设置为与主进程中创建的
multiprocessing.event
对象相同的对象。最后,每个子进程都有一个名为
event
的全局变量,该变量引用同一
multiprocessing.event
对象。这将允许您从主进程向子进程发送信号,就像您希望的那样。请参见此示例:

import multiprocessing

event = None
def my_setup(event_):
  global event
  event = event_
  print "event is %s in child" % event


if __name__ == "__main__":
    event = multiprocessing.Event()
    p = multiprocessing.Pool(2, my_setup, (event,))
    print "event is %s in parent" % event
    p.close()
    p.join()
输出:

dan@dantop2:~$ ./mult.py 
event is <multiprocessing.synchronize.Event object at 0x7f93cd7a48d0> in child
event is <multiprocessing.synchronize.Event object at 0x7f93cd7a48d0> in child
event is <multiprocessing.synchronize.Event object at 0x7f93cd7a48d0> in parent
dan@dantop2:~$ ./mult.py 
event is <multiprocessing.synchronize.Event object at 0x7fea3b1dc8d0> in child
event is <multiprocessing.synchronize.Event object at 0x7fea3b1dc8d0> in child
event is <multiprocessing.synchronize.Event object at 0x7fea3b1dc8d0> in parent
main is sleeping
    <Process(PoolWorker-1, started daemon)> is waiting
    <Process(PoolWorker-2, started daemon)> is waiting
    <Process(PoolWorker-4, started daemon)> is waiting
    <Process(PoolWorker-3, started daemon)> is waiting
main is setting event
    <Process(PoolWorker-2, started daemon)> has woken up
    <Process(PoolWorker-1, started daemon)> has woken up
    <Process(PoolWorker-4, started daemon)> has woken up
    <Process(PoolWorker-3, started daemon)> has woken up
输出:

dan@dantop2:~$ ./mult.py 
event is <multiprocessing.synchronize.Event object at 0x7f93cd7a48d0> in child
event is <multiprocessing.synchronize.Event object at 0x7f93cd7a48d0> in child
event is <multiprocessing.synchronize.Event object at 0x7f93cd7a48d0> in parent
dan@dantop2:~$ ./mult.py 
event is <multiprocessing.synchronize.Event object at 0x7fea3b1dc8d0> in child
event is <multiprocessing.synchronize.Event object at 0x7fea3b1dc8d0> in child
event is <multiprocessing.synchronize.Event object at 0x7fea3b1dc8d0> in parent
main is sleeping
    <Process(PoolWorker-1, started daemon)> is waiting
    <Process(PoolWorker-2, started daemon)> is waiting
    <Process(PoolWorker-4, started daemon)> is waiting
    <Process(PoolWorker-3, started daemon)> is waiting
main is setting event
    <Process(PoolWorker-2, started daemon)> has woken up
    <Process(PoolWorker-1, started daemon)> has woken up
    <Process(PoolWorker-4, started daemon)> has woken up
    <Process(PoolWorker-3, started daemon)> has woken up
现在,回到您对
事件
工作方式的误解<代码>事件
的用法如下:

import time
import multiprocessing

def event_func(num):
    print '\t%r is waiting' % multiprocessing.current_process()
    event.wait()
    print '\t%r has woken up' % multiprocessing.current_process()

if __name__ == "__main__":
    event = multiprocessing.Event()

    pool = multiprocessing.Pool()
    a = pool.map_async(event_func, [i for i in range(pool._processes)])

    print 'main is sleeping'
    time.sleep(2)

    print 'main is setting event'
    event.set()

    pool.close()
    pool.join()
输出:

dan@dantop2:~$ ./mult.py 
event is <multiprocessing.synchronize.Event object at 0x7f93cd7a48d0> in child
event is <multiprocessing.synchronize.Event object at 0x7f93cd7a48d0> in child
event is <multiprocessing.synchronize.Event object at 0x7f93cd7a48d0> in parent
dan@dantop2:~$ ./mult.py 
event is <multiprocessing.synchronize.Event object at 0x7fea3b1dc8d0> in child
event is <multiprocessing.synchronize.Event object at 0x7fea3b1dc8d0> in child
event is <multiprocessing.synchronize.Event object at 0x7fea3b1dc8d0> in parent
main is sleeping
    <Process(PoolWorker-1, started daemon)> is waiting
    <Process(PoolWorker-2, started daemon)> is waiting
    <Process(PoolWorker-4, started daemon)> is waiting
    <Process(PoolWorker-3, started daemon)> is waiting
main is setting event
    <Process(PoolWorker-2, started daemon)> has woken up
    <Process(PoolWorker-1, started daemon)> has woken up
    <Process(PoolWorker-4, started daemon)> has woken up
    <Process(PoolWorker-3, started daemon)> has woken up
main正在睡觉
正在等待
正在等待
正在等待
正在等待
主要是设置事件
他醒了
他醒了
他醒了
他醒了

如您所见,子进程需要显式调用
event.wait()
,才能暂停它们。当在主进程中调用
event.set
时,它们将取消暂停。现在,没有工作人员正在调用
事件。请稍候
,因此他们中的任何人都无法暂停。我建议您查看文档,其中
multiprocessing.Event
replicates.

您在哪里找到此代码的?这是Stackoverflow上建议的。我已询问如何暂停/重新启动池。这就是建议。我知道这不是政策,但谢谢!很好的信息性回答,加上额外的背景知识。非常有帮助!注意:在我的系统(macOSX-10.13.6、python-3.7.6、eclipse-4.11.0)上,如果您的启动进程是“spawn”,即多处理。set_start_方法(“spawn”,force=True),此解决方案将不起作用。(由此产生的“failure”很有趣,因为没有生成错误,但是,代码只在event_func()中的event.wait()行停止。)这很重要,因为“spawn”是MacOSX上python 3.8的默认start_方法。另外请注意:如果使用“pool.map()”,则上述代码中存在显著差异(如果start_方法是“spawn”,则会抛出一条错误消息),而不是“pool.map_async()”(其中不会生成错误,但代码会失败)。最终,我放弃了“pool”,并使用多个单独的进程来实现更干净的执行(如:“multiprocessing.Process(target=runGUIthread_v2,args=(myEvent,yearParams,)))。