尝试在multiprocessing
list-variable'poolList`中存储multiprocessing
的进程实例时,我收到以下异常:
SimpleQueue objects should only be shared between processes through inheritance
我想将PROCESS实例存储在变量中的原因是为了能够稍后终止所有或仅仅其中一些(例如,如果一个进程冻结)。如果在变量中存储PROCESS不是一个选项,我想知道如何获取或列出由mutliprocessing
POOL启动的所有PROCESSES。这与.current_process()
方法的作用非常相似。除了.current_process
只需要一个进程,而我需要启动所有进程或当前正在运行的所有进程。
两个问题:
甚至可以存储流程的实例(由于mp.current_process()
目前我只能从流程运行的函数内部获取单个进程(使用myFunct()
方法从.current_process()
内部)。
相反,我想列出multiprocessing
当前运行的所有进程。如何实现呢?
import multiprocessing as mp
poolList=mp.Manager().list()
def myFunct(arg):
print 'myFunct(): current process:', mp.current_process()
try: poolList.append(mp.current_process())
except Exception, e: print e
for i in range(110):
for n in range(500000):
pass
poolDict[arg]=i
print 'myFunct(): completed', arg, poolDict
from multiprocessing import Pool
pool = Pool(processes=2)
myArgsList=['arg1','arg2','arg3']
pool=Pool(processes=2)
pool.map_async(myFunct, myArgsList)
pool.close()
pool.join()
答案 0 :(得分:5)
列出由Pool() - 实例启动的进程(如果我理解正确的话,这就是你的意思),有pool._pool-list。它包含流程的实例。
但是,它不是文档化界面的一部分,因此,实际上不应该使用它。 但是......似乎有点不太可能会像那样改变。我的意思是,他们是否应该停止在池中有一个内部进程列表?而不是叫那个_pool? 而且,令我很生气的是,至少不是一个获取流程的方法。或者其他的东西。 并且由于某些名称更改而导致的处理不应该那么困难。
但是,使用风险依然存在:
from multiprocessing import pool
# Have to run in main
if __name__ == '__main__':
# Create 3 worker processes
_my_pool = pool.Pool(3)
# Loop, terminate, and remove from the process list
# Use a copy [:] of the list to remove items correctly
for _curr_process in _my_pool._pool[:]:
print("Terminating process "+ str(_curr_process.pid))
_curr_process.terminate()
_my_pool._pool.remove(_curr_process)
# If you call _repopulate, the pool will again contain 3 worker processes.
_my_pool._repopulate_pool()
for _curr_process in _my_pool._pool[:]:
print("After repopulation "+ str(_curr_process.pid))
该示例创建一个池并手动终止所有进程。
重要的是,您要记得自己删除从池中终止的进程,我希望Pool()继续照常工作。
_my_pool._repopulate再次将工作进程数增加到3,不需要回答问题,但会给出一些幕后洞察力。
答案 1 :(得分:2)
您正在创建托管List
对象,但随后让关联的Manager
对象过期。
Process
个对象是可共享的,因为它们不会被发现;也就是说,它们并不简单。
奇怪的是,multiprocessing
模块没有等同于threading.enumerate()
- 也就是说,无法列出所有未完成的流程。作为一种解决方法,我只是将procs存储在列表中。我从不terminate()
进程,而是在父进程sys.exit(0)
。这很粗糙,因为工人会把事情处于不一致的状态,但是对于较小的程序来说这是可以的
为了杀死冷冻工人,我建议:1)工人接受心跳"心跳"队列中的作业偶尔出现,2)如果父母通知工作人员A在一定时间内没有响应心跳,则p.terminate()
。考虑在另一个SO问题中重述问题,因为它很有趣。
老实说,map
的东西比使用管理器容易得多。
这是我使用过的经理示例。工作人员将内容添加到共享列表中。另一名工人偶尔会醒来,处理清单上的所有内容,然后再回到睡眠状态。该代码还具有详细日志,这对于简化调试至关重要。
# producer adds to fixed-sized list; scanner uses them
import logging, multiprocessing, sys, time
def producer(objlist):
'''
add an item to list every sec; ensure fixed size list
'''
logger = multiprocessing.get_logger()
logger.info('start')
while True:
try:
time.sleep(1)
except KeyboardInterrupt:
return
msg = 'ding: {:04d}'.format(int(time.time()) % 10000)
logger.info('put: %s', msg)
del objlist[0]
objlist.append( msg )
def scanner(objlist):
'''
every now and then, run calculation on objlist
'''
logger = multiprocessing.get_logger()
logger.info('start')
while True:
try:
time.sleep(5)
except KeyboardInterrupt:
return
logger.info('items: %s', list(objlist))
def main():
logger = multiprocessing.log_to_stderr(
level=logging.INFO
)
logger.info('setup')
# create fixed-length list, shared between producer & consumer
manager = multiprocessing.Manager()
my_objlist = manager.list( # pylint: disable=E1101
[None] * 10
)
multiprocessing.Process(
target=producer,
args=(my_objlist,),
name='producer',
).start()
multiprocessing.Process(
target=scanner,
args=(my_objlist,),
name='scanner',
).start()
logger.info('running forever')
try:
manager.join() # wait until both workers die
except KeyboardInterrupt:
pass
logger.info('done')
if __name__=='__main__':
main()
答案 2 :(得分:1)
是的,您可以获取所有活动的进程并根据进程名称执行操作 例如
multiprocessing.Process(target=foo, name="refresh-reports")
然后
for p in multiprocessing.active_children():
if p.name == "foo":
p.terminate()