我有一个Python多处理模块的简单实现
if __name__ == '__main__':
jobs = []
while True:
for i in range(40):
# fetch one by one from redis queue
#item = item from redis queue
p = Process(name='worker '+str(i), target=worker, args=(item,))
# if p is not running, start p
if not p.is_alive():
jobs.append(p)
p.start()
for j in jobs:
j.join()
jobs.remove(j)
def worker(url_data):
"""worker function"""
print url_data['link']
我期望这段代码做什么:
- 无限循环运行,一直等待Redis队列。
- 如果 Redis 队列不为空,则获取项目。
- 创建 40 个 multiprocess.Process,不多不少
- 如果一个进程已完成处理,则启动新进程,以便约 40 个进程始终在运行。
我读到,为了避免僵尸进程应该绑定(bind)(加入)到父进程,这就是我期望在第二个循环中实现的目标。但问题是,启动时它会生成 40 个进程,工作人员完成处理并进入僵尸状态,直到所有当前生成的进程尚未完成, 然后在“while True”的下一次迭代中,相同的模式继续。
所以我的问题是: 如何避免僵尸进程。并在 40 个进程中的 1 个完成后立即生成新进程
最佳答案
对于像您所描述的那样的任务,通常最好使用使用池
的不同方法。
您可以让主进程获取数据,然后由工作进程处理它。
以下是 Python Docs 中的 Pool
示例
def f(x):
return x*x
if __name__ == '__main__':
pool = Pool(processes=4) # start 4 worker processes
result = pool.apply_async(f, [10]) # evaluate "f(10)" asynchronously
print result.get(timeout=1) # prints "100" unless your computer is *very* slow
print pool.map(f, range(10)) # prints "[0, 1, 4,..., 81]"
我还建议使用 imap
而不是 map
,因为您的任务似乎可以异步。
您的代码大致如下:
p = Pool(40)
while True:
items = items from redis queue
p.imap_unordered(worker, items) #unordered version is faster
def worker(url_data):
"""worker function"""
print url_data['link']
关于python 多处理僵尸进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30845727/