主進程被殺死時,如何保證子進程同時退出,而不變為孤兒進程(二)


  之前文章討論了進程意外退出時,如何將主進程創建的子進程終止,避免形成孤兒進程,兩種做法,一種是將是將主進程中創建的子進程信息保存,使用信號處理機制,在主進程收到終止信號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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM