• 主进程被杀死时,如何保证子进程同时退出,而不变为孤儿进程(二)


      之前文章讨论了进程意外退出时,如何将主进程创建的子进程终止,避免形成孤儿进程,两种做法,一种是将是将主进程中创建的子进程信息保存,使用信号处理机制,在主进程收到终止信号SIGTERM时,保存的子进程信息terminate,之后主进程退出;另一种是更加直接,通过进程组id将整个进程组中的进程杀死。这两种方式主要的差别是,第一种方式是通过向主进程发送SIGTERM请求来杀死主进程和其子进程的,而第二种方式主进程和其子进程都可以收到SIGTERM,将进程组中的所有进程杀死。

      这节我们继续研究下上节第一种方法示例中的代码。代码中用一个全局的processes变量保存子进程信息,这是因为标准库中signal.signal方法接收的回调函数action,包含两个参数,拥有各自的含义,所以没有办法,将子进程信息通过参数传递给action回调函数:

    signal(sig, action) -> action
        Set the action for the given signal.  The action can be SIG_DFL, SIG_IGN, or a callable Python object.  The previous action is returned.  
        See getsignal() for possible return values.
        
        *** IMPORTANT NOTICE ***
        A signal handler function is called with two arguments:
        the first is the signal number, the second is the interrupted stack frame.

      那么有没有更优雅的做法,能够将processes通过函数调用,传递给回调函数,避免使用全局变量呢?答案是肯定得。python标准库functools向我们提供了partial偏函数,它的用途是让一些参数在函数被调用之前提前获知其值,位置参数和关键字参数均可应用,我们来看个例子:

    from functools import partial
    def add(a, b):
        return a + b
    
    add_with_hundred = partial(add, 100)
    result = add_with_hundred(10)
    print result
    110

        代码示例中,partial(add, 100)返回一个partial对象,参数add表示要封装的方法,参数100表示位置参数,它表示的位置是add方法中第一个参数,相当于对add方法的第一个参数添加了默认值100,对于返回的add_with_hundred对象,它的第一个参数默认已经是100,那么在使用时只需要传入一个参数即可。再来看一个关键字参数的例子:

    from functools import partial
    basetwo = partial(int, base=2)
    result = basetwo('101')
    print result
    5

         int方法用于将字符串类型的变量转换为整型,第二个参数base表示以base进制进行转换。代码中,partial(int, base=2)指定了返回的对象basetwo,以2进制进行转换。通过这两个例子,我们了解了partial方法的用途,我们就可以对上节的代码进行简单的修改,来避免出现全局变量的使用:  

     1 def term(t_processes, sig_num, frame):
     2     print 'terminate process %d' % os.getpid()
     3     try:
     4         print 'the processes is %s' % processes
     5         for p in processes:
     6             print 'process %d terminate' % p.pid
     7             p.terminate()
     8     except Exception as e:
     9         print str(e)
    10 
    11 
    12 if __name__ == '__main__':
    13     print 'current main-process pid is %s' % os.getpid()
    14     processes = [] 
    15     for i in range(3):
    16         t = Process(target=fun, args=(str(i),))
    17         t.daemon = True
    18         t.start()
    19         processes.append(t)
    20     
    21     # handler使用partital处理,用local processes对term方法的第一个参数进行绑定
    22     handler = functools.partial(term, processes)
    23     signal.signal(signal.SIGTERM, handler)
    24     try:
    25         for p in processes:
    26             p.join()
    27     except Exception as e:
    28         print str(e)
  • 相关阅读:
    POJ 2000 Gold Coins
    HDU 5804 Price List
    POJ 1316 Self Numbers
    HDU 5783 Divide the Sequence
    rabbitmq基础使用
    centos7安装RabbitMQ
    编程之路┊一个程序员走过的路
    jquery layer弹出层插件
    SWFUpload 2.5.0版 官方说明文档 中文翻译版
    C# 格式化字符串,日期,字符串操作汇总
  • 原文地址:https://www.cnblogs.com/Tour/p/5191056.html
Copyright © 2020-2023  润新知