zoukankan      html  css  js  c++  java
  • ctrl+c关闭多线程python程序

    项目中经常需要用到多线程,如果一个python程序用了多线程,当子线程没有结束时,用ctrl+c是关闭不了主线程的,这时候就只能用kill命令杀掉,这样会很麻烦。

    所以探讨了下怎么ctrl+C关闭多线程python程序,也在网上查了很多别人的做法,自己做了很多实验,尝试了很多种方法,总结得出一个能用的方法就是,把子线程setDeamon(True),通过isAlive方法实现join的功能。

    代码:

    #encoding=utf-8
    __author__ = 'kevinlu1010@qq.com'
    import threading
    from time import sleep
    def f():
            sleep(100)
    p=threading.Thread(target=f)
    p.setDaemon(True)
    p.start()
    # p.join()
    while 1:
        if not p.isAlive():
            break
        sleep(1)
    print 'done'

    当子线程很多的时候,可以用这个函数

    def threads_join(threads):
        '''
        令主线程阻塞,等待子线程执行完才继续,使用这个方法比使用join的好处是,可以ctrl+c kill掉进程
        '''
        for t in threads:
            while 1:
                if t.isAlive():
                    sleep(10)
                else:
                    break

    这种做法的坏处就是令主线程阻塞,直到子线程执行完这个功能的实现太麻烦了,原本用join来实现就好方便很多

    下面是研究的过程中的尝试,但是全部都实现不了ctrl+C关闭的功能

    原始的多线程程序

    def f():
        sleep(100)
    p=threading.Thread(target=f)
    p.start()
    p.join()
    
    print 'done'

    这是最原始的一个多线程程序。

    尝试一:设置线程为守护线程,即加入

    p.setDaemon(True)

    但是ctrl+c,程序没反应,跟没加是一样的

    尝试二:使用信号,因为ctrl c的时候系统会向程序发送sigint信号,所以我们可以令程序捕获这个信号,并调用os的kill方法杀死自己

    import signal
    import os
    import threading
    from time import sleep
    def f(a,b):
        print 'kill me'
        os.kill(os.getpid(),signal.SIGKILL)
    
    def tf():
        sleep(20)
    
    signal.signal(signal.SIGINT,f)
    p=threading.Thread(target=tf)
    p.start()
    p.join()
    
    print 'done'

    程序运行后,我立刻按ctrl c ,主线程会等子线程sleep20后,才会print 'kill me',证明主线程在等待子线程执行的时候,即join的时候,是捕获不了系统发来的信号的,要等子线程执行完毕,才能捕获。所以这个方法还是不行。

    尝试三,用一个标志来让子线程自己结束自己的运行

    is_exit=0
    def f(a,b):
        global is_exit
        is_exit=1
        print 'kill me'
        os.kill(os.getpid(),signal.SIGKILL)
    
    def tf():
        while not is_exit:
            sleep(20)
    
    signal.signal(signal.SIGINT,f)
    p=threading.Thread(target=tf)
    p.start()
    while 1:
        sleep(10)
    
    print 'done'

    这里加入一个标志is_exit用来标志子线程是否继续执行,然后加入信号,当捕获关闭信号时,把is_exit改为1,令到子线程自己结束,由于主线程在join的状态下是接受不了信号的,所以这里让主线程处于一直等待的状态。

    这个做法是能做到ctrl c关闭子线程的,缺点就是子线程需要做完一个循环才能结束,同时主线程没有了join的功能,适用于主线程在给子线程发放任务后就不需要做任何操作的情形。

    所以总的来说,ctrl c不能关闭多线程的程序的主要原因是使用了join方法,一旦用了join,主线程就会一直处于阻塞状态,不接受任何外界的联系。但是join方法在实际的业务中是经常需要用到的,我查了很久也没有查到可以替代join的,同时可以被ctrl c的方法。上面第一个程序用到的使用alive方法来实现join的功能的做法算是一个不太好,但又不能不使用它的解决方案了,希望后面能找到更好的实现join功能的方法。

  • 相关阅读:
    HDU2586 How far away?(tarjan的LCA)
    You Raise Me Up
    POJ2891 Strange Way to Express Integers(中国剩余定理)
    POJ2142 The Balance(扩展欧几里得)
    HDU 1166模仿大牛写的线段树
    NetWord Dinic
    HDU 1754 线段树裸题
    hdu1394 Minimum Inversion Number
    hdu2795 Billboard
    【完全版】线段树
  • 原文地址:https://www.cnblogs.com/Xjng/p/3946222.html
Copyright © 2011-2022 走看看