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

python 如何优雅地退出子进程的更多相关文章

  1. 如何优雅地退出python程序

    如何优雅地退出python程序 一个单模的python程序,启动之后要能够优雅地关闭.即当用户按Ctrl+C或者kill pid的时候,程序都能从容关闭.实现起来非常简单. is_running = ...

  2. 情景linux--如何优雅地退出telnet

    情景linux--在脚本中如何优雅地退出telnet 情景 telnet命令是TELNET协议的用户接口,它支持两种模式:命令模式和会话模式.虽然telnet支持许多命令,但大部分情况下,我们只是使用 ...

  3. C# Note11:如何优雅地退出WPF应用程序

    前言 I should know how I am supposed to exit my application when the user clicks on the Exit menu item ...

  4. 从nsq中学习如何优雅的退出go 网络程序

    退出运行中的程序,可以粗暴的kill -9 $PID,但这样会破坏业务的完整性,有可能一个正在在执行的逻辑半途而费,从而产生不正常的垃圾数据. 本文总结在go语言中,如何能优雅的退出网络应用,涉及的知 ...

  5. 如何优雅的退出/关闭/重启gunicorn进程

    在工作中,会发现gunicorn启动的web服务,无论怎么使用kill -9 进程号都是无法杀死gunicorn,经过我一番百度和谷歌,发现想要删除gunicorn进程其实很简单. 1. 寻找mast ...

  6. 【Golang】程序如何优雅的退出?

    1. 背景 项目开发过程中,随着需求的迭代,代码的发布会频繁进行,在发布过程中,如何让程序做到优雅的退出? 为什么需要优雅的退出? 你的 http 服务,监听端口没有关闭,客户的请求发过来了,但处理了 ...

  7. 让Python更优雅更易读(第二集)

    友情链接 让Python更优雅更易读(第一集) 1.装饰器 1.1装饰器特别适合用来实现以下功能 运行时校验:在执行阶段进行特定校验,当校验通不过时终止执行. 适合原因:装饰器可以方便地在函数执行前介 ...

  8. [转载]Python模块学习 ---- subprocess 创建子进程

    [转自]http://blog.sciencenet.cn/blog-600900-499638.html 最近,我们老大要我写一个守护者程序,对服务器进程进行守护.如果服务器不幸挂掉了,守护者能即时 ...

  9. 一个Python中优雅的数据分块方法

    背景 看到这个标题你可能想一个分块能有什么难度?还值得细说吗,最近确实遇到一个有意思的分块函数,写法比较巧妙优雅,所以写一个分享. 日前在做需求过程中有一个对大量数据分块处理的场景,具体来说就是几十万 ...

随机推荐

  1. python3+dlib人脸识别及情绪分析

    一.介绍 我想做的是基于人脸识别的表情(情绪)分析.看到网上也是有很多的开源库提供使用,为开发提供了很大的方便.我选择目前用的比较多的dlib库进行人脸识别与特征标定.使用python也缩短了开发周期 ...

  2. P3928 SAC E#1 - 一道简单题 Sequence2

    题目背景 小强和阿米巴是好朋友. 题目描述 小强喜欢数列.有一天,他心血来潮,写下了三个长度均为n的数列. 阿米巴也很喜欢数列.但是他只喜欢其中一种,波动数列. 阿米巴把他的喜好告诉了小强.小强便打算 ...

  3. [USACO16OPEN]关闭农场Closing the Farm_Silver

    题目描述 FJ和他的奶牛们正在计划离开小镇做一次长的旅行,同时FJ想临时地关掉他的农场以节省一些金钱. 这个农场一共有被用M条双向道路连接的N个谷仓(1<=N,M<=3000).为了关闭整 ...

  4. [Codeforces]848C - Goodbye Souvenir

    题目大意:n个数字,m次操作,支持修改一个数字和查询一个区间内每种数字最大出现位置减最小出现位置的和.(n,m<=100,000) 做法:把每个数字表示成二维平面上的点,第一维是在数组中的位置, ...

  5. poj 2653 线段与线段相交

    Pick-up sticks Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 11884   Accepted: 4499 D ...

  6. SpringMvc+Spring+MyBatis 基于注解整合

    最近在给学生们讲Spring+Mybatis整合,根据有的学生反映还是基于注解实现整合便于理解,毕竟在先前的工作中团队里还没有人完全舍弃配置文件进行项目开发,由于这两个原因,我索性参考spring官方 ...

  7. Django中Form的基本使用

    from django import forms from django.forms import fields class UserInfo(forms.Form): username = fiel ...

  8. TensorFlow Serving-TensorFlow 服务

    TensorFlow服务是一个用于服务机器学习模型的开源软件库.它处理机器学习的推断方面,在培训和管理他们的生命周期后采取模型,通过高性能,引用计数的查找表为客户端提供版本化访问. 可以同时提供多个模 ...

  9. TeamViewer 服务队列网页怎么打开?有什么用?

    熟悉一款软件,除了要熟悉它的界面,还应该熟悉它的网站.可能会有很多人说,网站我当然知道了.但是TeamViewer的服务队列页面你真的熟悉吗?所以,今天小编就带大家深入的了解一下TeamViewer服 ...

  10. php+xdebug+dbgp远程调试(多人)

    目录 创建 DBGP 服务 配置 调试 创建 DBGP 服务 到 下载页面,下载 python 版本的 dbgp 到服务器上. 解压后执行 pydbgpproxy. 如果提示找不到 dbgp 模块,则 ...