Python多进程进程从不终止
下面我的例程获取一个urllib2.Requests列表,并为每个请求生成一个新进程,然后将其触发。它的目的是为了实现异步速度,所以它完全是一劳永逸的(不需要响应)。问题是下面代码中生成的进程永远不会终止。因此,在这些之后,盒子将发出隆隆声。上下文:Django web应用程序。有什么帮助吗Python多进程进程从不终止,python,django,process,multiprocess,Python,Django,Process,Multiprocess,下面我的例程获取一个urllib2.Requests列表,并为每个请求生成一个新进程,然后将其触发。它的目的是为了实现异步速度,所以它完全是一劳永逸的(不需要响应)。问题是下面代码中生成的进程永远不会终止。因此,在这些之后,盒子将发出隆隆声。上下文:Django web应用程序。有什么帮助吗 MP_CONCURRENT = int(multiprocessing.cpu_count()) * 2 if MP_CONCURRENT < 2: MP_CONCURRENT = 2 MPQ = m
MP_CONCURRENT = int(multiprocessing.cpu_count()) * 2
if MP_CONCURRENT < 2: MP_CONCURRENT = 2
MPQ = multiprocessing.JoinableQueue(MP_CONCURRENT)
def request_manager(req_list):
try:
# put request list in the queue
for req in req_list:
MPQ.put(req)
# call processes on queue
worker = multiprocessing.Process(target=process_request, args=(MPQ,))
worker.daemon = True
worker.start()
# move on after queue is empty
MPQ.join()
except Exception, e:
logging.error(traceback.print_exc())
# prcoess requests in queue
def process_request(MPQ):
try:
while True:
req = MPQ.get()
dr = urllib2.urlopen(req)
MPQ.task_done()
except Exception, e:
logging.error(traceback.print_exc())
MP\u CONCURRENT=int(multiprocessing.cpu\u count())*2
如果MP_CONCURRENT<2:MP_CONCURRENT=2
MPQ=多处理.可连接队列(MP\U并发)
def请求管理器(请求列表):
尝试:
#将请求列表放入队列中
对于req_列表中的req:
MPQ.put(要求)
#队列上的调用进程
worker=multiprocessing.Process(target=Process\u请求,args=(MPQ,))
worker.daemon=True
worker.start()
#队列为空后继续
MPQ.join()
除例外情况外,e:
logging.error(traceback.print\u exc())
#队列中的请求
def处理请求(MPQ):
尝试:
尽管如此:
req=MPQ.get()
dr=urllib2.urlopen(请求)
MPQ.task_done()
除例外情况外,e:
logging.error(traceback.print\u exc())
MP\u CONCURRENT=int(多处理.cpu\u count())*2
如果MP_CONCURRENT<2:MP_CONCURRENT=2
MPQ=多处理.可连接队列(MP\U并发)
CHUNK_SIZE=20#发送到一个进程的请求数。
池=多处理。池(MP\U并发)
def请求管理器(请求列表):
尝试:
#将请求列表放入队列中
responce=pool.map(process_request,req_list,CHUNK_SIZE)#函数在调用所有请求和池工作结束后退出
#或
responce=pool.map_async(进程请求、请求列表、块大小)#函数请求管理器在所有请求传递到池后退出
除例外情况外,e:
logging.error(traceback.print\u exc())
#队列中的请求
def处理请求(req):
dr=urllib2.urlopen(请求)
这比你的代码快5-10倍也许我不对,但是
MP_CONCURRENT = int(multiprocessing.cpu_count()) * 2
if MP_CONCURRENT < 2: MP_CONCURRENT = 2
MPQ = multiprocessing.JoinableQueue(MP_CONCURRENT)
def request_manager(req_list):
try:
# put request list in the queue
pool=[]
for req in req_list:
MPQ.put(req)
# call processes on queue
worker = multiprocessing.Process(target=process_request, args=(MPQ,))
worker.daemon = True
worker.start()
pool.append(worker)
# move on after queue is empty
MPQ.join()
# Close not needed processes
for p in pool: p.terminate()
except Exception, e:
logging.error(traceback.print_exc())
# prcoess requests in queue
def process_request(MPQ):
try:
while True:
req = MPQ.get()
dr = urllib2.urlopen(req)
MPQ.task_done()
except Exception, e:
logging.error(traceback.print_exc())
MP\u CONCURRENT=int(multiprocessing.cpu\u count())*2
如果MP_CONCURRENT<2:MP_CONCURRENT=2
MPQ=多处理.可连接队列(MP\U并发)
def请求管理器(请求列表):
尝试:
#将请求列表放入队列中
池=[]
对于req_列表中的req:
MPQ.put(要求)
#队列上的调用进程
worker=multiprocessing.Process(target=Process\u请求,args=(MPQ,))
worker.daemon=True
worker.start()
pool.append(工作者)
#队列为空后继续
MPQ.join()
#关闭不需要的流程
对于池中的p:p.terminate()
除例外情况外,e:
logging.error(traceback.print\u exc())
#队列中的请求
def处理请求(MPQ):
尝试:
尽管如此:
req=MPQ.get()
dr=urllib2.urlopen(请求)
MPQ.task_done()
除例外情况外,e:
logging.error(traceback.print\u exc())
将侧边“brocker”集成到django(例如rabbitmq
或类似的东西)。好的,在做了一些小动作(并睡了一个好觉)之后,我相信我已经解决了问题(谢谢你,Eri,你是我需要的灵感)。僵尸进程的主要问题是,我没有发回信号说进程已经完成(并杀死它),我(天真地)认为这两个进程是通过多进程自动发生的
有效的代码:
# function that will be run through the pool
def process_request(req):
try:
dr = urllib2.urlopen(req, timeout=30)
except Exception, e:
logging.error(traceback.print_exc())
# process killer
def sig_end(r):
sys.exit()
# globals
MP_CONCURRENT = int(multiprocessing.cpu_count()) * 2
if MP_CONCURRENT < 2: MP_CONCURRENT = 2
CHUNK_SIZE = 20
POOL = multiprocessing.Pool(MP_CONCURRENT)
# pool initiator
def request_manager(req_list):
try:
resp = POOL.map_async(process_request, req_list, CHUNK_SIZE, callback=sig_end)
except Exception, e:
logging.error(traceback.print_exc())
将在池中运行的函数
def处理请求(req):
尝试:
dr=urllib2.urlopen(请求,超时=30)
除例外情况外,e:
logging.error(traceback.print\u exc())
#进程杀手
def信号终端(右):
sys.exit()
#全球的
MP\u CONCURRENT=int(多处理.cpu\u count())*2
如果MP_CONCURRENT<2:MP_CONCURRENT=2
块大小=20
池=多处理。池(MP\U并发)
#池启动器
def请求管理器(请求列表):
尝试:
resp=POOL.map\u async(进程请求、请求列表、块大小、回调=sig\u结束)
除例外情况外,e:
logging.error(traceback.print\u exc())
几点注意:
1) 必须首先(在全局声明之前)定义“map\u async”(“本例中为process\u request”)将命中的函数
2) 可能有一种更优雅的方式退出流程(欢迎建议)
3) 在本例中使用pool确实是最好的(再次感谢Eri),因为“回调”特性允许我立即抛出信号 while True:-有终止吗?我尝试了几种不同的方法,包括terminate()、重新扫描全局变量、休眠和终止、join()和no join()。到目前为止,唯一有效的方法是执行time.sleep(1),然后执行worker.terminate(),但这会中断整个过程,并且无法通过数千个潜在请求进行睡眠:(在回答您的问题时:当队列清空时,True是满意的(我知道,这不是很直观).
除了Queue.Empty,e:logging.info('task done');除了Exception,e:logging.error(traceback.print_exc())
您的解决方案不太好,我建议使用大共享池和map_async而不是Queue。感谢您的快速回复,但是这不起作用。它使用了两倍的内存和几乎两倍的进程(267对150我的方式运行相同的例程)。进程仍然是孤立的(完整的内存泄漏)。pool=multiprocessing.pool(MP_并发)必须在模块中,而不是在函数中,它消除了大约20%的额外进程,但我认为这是由于在某些情况下进程处于非活动状态之前终止了命中
# function that will be run through the pool
def process_request(req):
try:
dr = urllib2.urlopen(req, timeout=30)
except Exception, e:
logging.error(traceback.print_exc())
# process killer
def sig_end(r):
sys.exit()
# globals
MP_CONCURRENT = int(multiprocessing.cpu_count()) * 2
if MP_CONCURRENT < 2: MP_CONCURRENT = 2
CHUNK_SIZE = 20
POOL = multiprocessing.Pool(MP_CONCURRENT)
# pool initiator
def request_manager(req_list):
try:
resp = POOL.map_async(process_request, req_list, CHUNK_SIZE, callback=sig_end)
except Exception, e:
logging.error(traceback.print_exc())