当我使用Ctrl + c终止我的Python脚本时,内部会发生什么?

时间:2014-01-29 07:57:11

标签: python exception-handling

这些天我正在深入学习Python的异常处理功能。我遇到了exception SystemExit。在从official Python Docs阅读此内容时,我心里明白,当我通过按 Ctrl + c 来终止Python脚本时会发生什么?

让我们看看这个示例代码:

def func1(a,b):
    print "func1: "+str(a/b)
    #some more functions

def func2(a,b):
    print "func2: "+str(a/b)
    #some more functions

if __name__=="__main__":
    import random

    count=0
    for i in range(1000000):
            count=count+1
            print "count: "+str(count)
            try:
                    func1(random.randint(-2,3),random.randint(-2,3))
            except KeyboardInterrupt:
                    raise
            except:
                    print "error in func1"
            try:
                    func2(random.randint(-2,3),random.randint(-2,3))
            except KeyboardInterrupt:
                    raise
            except:
                    print "error in func2"

            print "\n"

在此示例代码中,我正在捕捉KeyboardInterrupt,因此我可以通过按 Ctrl + c 来停止我的脚本。我是否应该抓住SystemExit来使这段代码更加成熟?如果是,那么为什么?实际上这个问题是我在标题上出现的主要问题的来源。所以不要认为我在一篇文章中提出两个不同的问题。

4 个答案:

答案 0 :(得分:4)

您通常无需捕捉SystemExit因为exit()sys.exit()功能正常运作的原因:

  

<强> sys.exit([参数])

     

退出Python。这是通过引发SystemExit异常来实现的,因此finally语句的try子句指定的清理操作得到遵守,并且可以拦截外层的退出尝试。

示例:

try:
    exit()
except SystemExit:
    print "caught"

因此,您通常不希望首先捕获所有异常(通过使用空except:子句)。最好的方法通常是使您的异常处理程序尽可能具体。否则,它会使您的应用程序调试异常困难,因为它要么完全隐藏错误,要么至少使得难以诊断细节。

答案 1 :(得分:1)

你的函数可以引发的唯一例外是ZeroDivisionError,所以你应该只抓住那个:

import random

if __name__ == "__main__":
    for count in range(1000000):
        print "count:", count

        try:
            func1(random.randint(-2, 3),random.randint(-2, 3))
        except ZeroDivisionError:
            print "error in func1"

        try:
            func2(random.randint(-2, 3),random.randint(-2, 3))
        except ZeroDivisionError:
            print "error in func2"

        print "\n"

答案 2 :(得分:1)

你的标题与你问题的主体有所不同。

  1. 标题:

    内部发生的事情是python捕获SIGINT并从中引发KeyboardInterrupt异常。

  2. 文字:

    您不想except:

    相反,你想要

    if __name__=="__main__":
        try:
            import random
    
            count=0
            for i in range(1000000):
                    count=count+1
                    print "count: "+str(count)
                    try:
                            func1(random.randint(-2,3),random.randint(-2,3))
                    except Exception, e:
                            print "error in func1", e # or something...
                    try:
                            func2(random.randint(-2,3),random.randint(-2,3))
                    except Exception, e:
                            print "error in func2", e # or something...
    
                    print "\n"
    except Exception: 
        raise # any other "normal" exception.
    except: # Here it is ok, as you handle most exceptions above.
        pass
    
  3. 通常应该处理的大多数“正常”异常来自Exception。那些具有内在意义且通常不应被捕获的(全球范围除外)不会derive from Exception

    这些是KeyboardInterruptSystemExitGeneratorExit

答案 3 :(得分:1)

如果你不确定你所调用的代码是什么异常会引发错误,那么你应该(按照优先顺序):

  1. 找出它所记录的内容并且只捕获
  2. 抓住Exception,而非一切。
  3. KeyboardInterruptSystemExit都不是Exception的子类,但用于指示错误的所有标准Python异常都是。