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

python 如何优雅地退出子进程

2016-07-13 15:54 567 查看

python 如何优雅地退出子进程

主进程产生子进程,子进程进入永久循环模式。当主进程要求子进程退出时,如何能安全地退出子进程呢?
参考一些代码,我写了这个例子。运行之后,用kill pid试试。pid是主进程的pid。当然子进程的也没问题。
1)如果kill pid为子进程的pid,当所有子进程都kill掉了,主进程就关闭了。这也是我们想要的结果。
2)如果kill pid为主进程的pid,主进程向子进程发送退出信号,然后等全部子进程关闭后退出。

保证了主进程在所有子进程退出之后退出。

#-*- coding: UTF-8 -*-
# graceful_exit_event.py
# UTF-8 without BOM
#
# refer:
# http://stackoverflow.com/questions/26414704/how-does-a-python-process-exit-gracefully-after-receiving-sigterm-while-waiting?rq=1 # http://www.cnblogs.com/kaituorensheng/p/4445418.html # init created: 2016-07-13
# last updated: 2016-07-14
#
#######################################################################
import os
import signal
import multiprocessing

class GracefulExitException(Exception):
@staticmethod
def sigterm_handler(signum, frame):
raise GracefulExitException()
pass

class GracefulExitEvent(object):
def __init__(self):
self.workers = []
self.exit_event = multiprocessing.Event()

# Use signal handler to throw exception which can be caught
# by worker process to allow graceful exit.
signal.signal(signal.SIGTERM, GracefulExitException.sigterm_handler)
pass

def reg_worker(self, wp):
self.workers.append(wp)
pass

def is_stop(self):
return self.exit_event.is_set()

def notify_stop(self):
self.exit_event.set()

def wait_all(self):
while True:
try:
for wp in self.workers:
wp.join()

print "main process(%d) exit." % os.getpid()
break
except GracefulExitException:
self.notify_stop()
print "main process(%d) got GracefulExitException." % os.getpid()
except Exception, ex:
self.notify_stop()
print "main process(%d) got unexpected Exception: %r" % (os.getpid(), ex)
break
pass

#######################################################################
def worker_proc(gee):
import sys, time
print "worker(%d) start ..." % os.getpid()
try:
while not gee.is_stop():
# do task job here
print ".",
time.sleep(1)
else:
print ""
print "worker process(%d) got exit event." % os.getpid()
print "worker process(%d) do cleanup..." % os.getpid()
time.sleep(1)
print "[%d] 3" % os.getpid()
time.sleep(1)
print "[%d] 2" % os.getpid()
time.sleep(1)
print "[%d] 1" % os.getpid()

except GracefulExitException:
print "worker(%d) got GracefulExitException" % os.getpid()
except Exception, ex:
print "Exception:", ex
finally:
print "worker(%d) exit." % os.getpid()
sys.exit(0)

if __name__ == "__main__":
import sys
print "main process(%d) start" % os.getpid()

gee = GracefulExitEvent()

# Start some workers process and run forever
for i in range(0, 10):
wp = multiprocessing.Process(target=worker_proc, args=(gee,))
wp.start()
gee.reg_worker(wp)

gee.wait_all()
sys.exit(0)

需要说明的是:
如果某个进程接受 kill pid,必须在该进程函数的最外层捕获: except GracefulExitException,
同时该进程函数内部调用捕获了 except Excetion,则必须在之前捕获GracefulExitException,
即:
      (2) 必须在(3)之前。否则同时去掉(2)和(3)。

def do_some_func():
try:
time.sleep(10)

blablabla

(1) except SomeError:
# 捕获特定的异常
pass

(2) except GracefulExitException:
# 接收 kill pid
pass

(3) except: # 不建议捕获默认异常, 否则必须在此之前捕获:GracefulExitException
pass

def some_process_main(gee):

try:

while not gee.is_stop():
do_some_func()

except GracefulExitException:
# 接收到了 kill pid, 设置中止循环
gee.notify_stop()
pass
except:
pass


   
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: