通过fork()运行多个子进程的最佳方法是什么?
有一个Python脚本需要通过fork()来创建多个子进程。这些子进程应该同时运行,而父进程则需要等待所有子进程完成。如果能给某个“慢”的子进程设置一个超时时间,那就更好了。父进程在收集完所有子进程后,才会继续执行脚本的其他部分。
那么,最好的解决办法是什么呢?谢谢。
4 个回答
1
传统的、类UNIX的方式与子进程进行沟通,就是打开管道,连接它们的标准输入和输出,然后在父进程中使用select()
这个系统调用来处理这些通信(在Python中可以通过select
模块来实现)。
如果你需要结束一个运行缓慢的子进程,你可以保存它的进程ID(这个ID是通过os.fork()
调用返回的),然后在不需要它的时候用os.kill()
来结束它。当然,能够明确地与子进程沟通,并告诉它自己关闭,可能会更干净一些。
7
Ephemient: 你代码里的每个子进程在完成工作后都会留在循环里。他们会不断地重新创建自己。而且,当children[]数组不为空时,新创建的子进程会尝试在循环结束时等待它们的兄弟进程。最终会导致某个进程崩溃。这里有一个解决办法:
import os, time
def doTheJob(job):
for i in xrange(10):
print job, i
time.sleep(0.01*ord(os.urandom(1)))
# random.random() would be the same for each process
jobs = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"]
imTheFather = True
children = []
for job in jobs:
child = os.fork()
if child:
children.append(child)
else:
imTheFather = False
doTheJob(job)
break
# in the meanwhile
# ps aux|grep python|grep -v grep|wc -l == 11 == 10 children + the father
if imTheFather:
for child in children:
os.waitpid(child, 0)
12
简单的例子:
import os
children = []
for job in jobs:
child = os.fork()
if child:
children.append(child)
else:
pass # really should exec the job
for child in children:
os.waitpid(child, 0)
如果要处理一个比较慢的子进程,稍微麻烦一些;你可以用 wait
来代替 waitpid
,然后从子进程的返回值中筛选出需要的,而不是一个一个地等待(像这里那样)。如果你设置一个 alarm
和一个 SIGALRM
处理器,你可以在指定的时间后终止等待。这些都是标准的UNIX操作,不是Python特有的……