您的位置:首页 > 编程语言 > Python开发

python中多进程的相关技术

2013-01-12 22:53 246 查看
--如何创建的子线程。

self.pid = os.fork()

if self.pid == 0:

code = process_obj._bootstrap()

sys.stdout.flush()

sys.stderr.flush()

os._exit(code)

os fork 创建了一个新的进程,该子进程和父进程唯一不同的就是Pid,父id的pid不为空,所以从这个判断条件开始两个进程已经开始

执行不同的代码。

其中_bootstrap函数,做了几件事情,初始化子进程的上下文环境,以及执行相应的函数,这段代码在process。run()函数中,和C的非常相似。

由于子进程是父进程的复制,所以按道理说,在执行完上述的代码后,应该会返回到主函数,因为父进程是这么干的。

但是由于在分支的代码块中,有一个exit的函数,所以就退出了,不会再返回主进程去跑父进程的代码块

--父线程如何监控子进程的状态

在主进程中,在创建了子进程之后,

有段代码如下:_current_process._children.add(self),会将刚创建的子进程添加到_children的列表里面,这样的话,父进程就维系了和子进程的关系。

并且将子进程的所有信息都放置在_children里面。

python的process的join是父进程在等待子进程结束的信息。如果子进程结束的话,

Process.join() 调用 Popen.wait(),而 wait() 内部则通过 poll() 调用 os.waitpid() 等待子进程终止。

每个子进程在执行完成后,都会有:util._exit_function(),先将子进程的子进程给清理干净。最后返回return exitcode

--子进程异常结束,父进程如何处理。

如果子进程运行异常,抛出了个异常,或者在进程的具体代码模块的执行中遇到了exit(0)的,父进程会捕获这些异常,并且正确返回。

子进程代码中如果return 或者没有返回,都是ok的。

子进程代码中如果有exit(-1),也是可以正常退出的。也是可以正常的把错误的输出和,正常的输出转向到控制台。

子进程代码中如果有跑出异常,那么也是可以将所有的信息输出。

子进程如果被异常终止了,那么该进程会属于正常终止,所有没有保存到磁盘的信息都会被丢失,父进程能够收到该子进程正常结束的消息,能够正常终止。

所以子进程中无论发生了什么,都会正常的返回,除非其中某个语句卡住了。

--如果子进程卡住了,那么父进程能做什么

正常情况下,子进程应该不会卡住的,但是比如读hdfs的文件,或者调用对方的http请求,都会出现卡住的情况。

那么我们尽量被保证不会这样的情况,都会设置timeout的时间。

一旦卡住,那么直接调用terminate ,那么就会出现僵尸进程。

dwdev 28346 28345 0 21:56 pts/0 00:00:00 [python] <defunct>

dwdev 28347 28345 0 21:56 pts/0 00:00:00 [python] <defunct>

这种情况一般是由于子进程的退出的时候,进程内部有些信息没有被处理完。

a=Queue()

b=Array('i',range(10))

for i in threadLen:

t=Process(target=worker,args=(a,b))

threads.append(t)

for i in threadLen:

threads[i].start()

for i in threadLen:

threads[i].terminate()

print "i is:"+str(i)

# threads[i].join()

print a.get()#在这里的时候卡住了。。

print b[0]

print b[1]

如果改成下面的形式,那么就可以自然退出。

t=Process(target=worker,args=(str(i)))

threads.append(t)

for i in threadLen:

threads[i].start()

for i in threadLen:

threads[i].terminate()

print "i is:"+str(i)

# threads[i].join()

print "finished"

这样就可以自然退出,

前面这个例子和后面这个例子,经过多次的测试,发现问题是由于queue这个对象造成的,

queue的对象中的get方法,当queue中没有对象的时候,那么就会卡住主进程,而此时子进程已经结束了,没有join的函数处理进程终止的信息。

导致子进程都变成僵尸进程。

如果在terminate之后,加了join的函数,那么就没有defunct的存在了。这个defunt就是子进程的信号没有被及时处理,导致子进程无法正常退出。
http://www.erlangsir.com/2011/04/22/python-library-multiprocessing/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: