zoukankan      html  css  js  c++  java
  • python之错误调试

      无论谁写的程序,必定会存在bug,解决bug需要我们去调试程序。于是乎,在Python中,就会好几种调试手段,如print、assert、logging、pdb、pdb.set_trace()

      一、使用print()函数直接打印

    >>> def foo(s):
    ...     n = int(s)
    ...     print(n)
    ...     return 10 / n
    ...
    >>> def main():
    ...     foo('0')
    ...
    >>> main()
    0
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 2, in main
      File "<stdin>", line 4, in foo
    ZeroDivisionError: division by zero

      我们可以在认为可能出错的地方打印变量,但这有很大的弊端,因为打印的代码没有实际功能,都是垃圾信息。而且print最后还得删除,所以第二种方法是用assert替代print

      二、使用断言assert

    >>> def foo(s):
    ...     n = int(s)
    ...     assert n != 0,'n的值是0!'
    ...     return 10 / n
    ...
    >>> def main():
    ...     foo('0')
    ...
    >>> main()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 2, in main
      File "<stdin>", line 3, in foo
    AssertionError: n的值是0!

      assert的意思,当后面的表达式为False时,就会抛出AssertionError,如果为True,什么都不做,直接到下一行。assert有一大特性:在启动python解释器的时候可以使用-O参数来关闭assert(大写的o)

    PS E:Python3.6.3workspace> python -O err_assert.py
    Traceback (most recent call last):
      File "err_assert.py", line 9, in <module>
        main()
      File "err_assert.py", line 7, in main
        foo('0')
      File "err_assert.py", line 4, in foo
        return 10 / n
    ZeroDivisionError: division by zer

      三、使用logging

    import logging
    logging.basicConfig(level=logging.INFO)
    s = '0'
    n = int(s)
    logging.info('n=%d' % n)
    print(10/n)
    
    #执行结果
    PS E:Python3.6.3workspace> python err_logginginfo.py
    INFO:root:n=0
    Traceback (most recent call last):
      File "err_logginginfo.py", line 6, in <module>
        print(10/n)
    ZeroDivisionError: division by zero

      使用logging不会抛出错误,直接输出到文件中。logging可以允许你指定记录信息的级别,级别由低到高分别是debug、info、warning、error、CRITICAL等级别,当定义高级别的时候,低级别的信息不会输出,这是把日志信息输出到控制台console,我们还可以通过设置把日志输出到文件中

      四、使用python的调试器pdb

      可以让程序以单步方式执行,方便我们随时查看运行状态

      新建程序err_pdb.py

    s = '0'
    n = int(s)
    print(10 / n)

      然后以pdb模式启动

    PS E:Python3.6.3workspace> python -m pdb err_pdb.py
    > e:python3.6.3workspaceerr_pdb.py(1)<module>()
    -> s = '0'
    (Pdb) l
      1  -> s = '0'
      2     n = int(s)
      3     print(10 / n)
    [EOF]
    (Pdb) n
    > e:python3.6.3workspaceerr_pdb.py(2)<module>()
    -> n = int(s)
    (Pdb) p s
    '0'
    (Pdb) p n
    *** NameError: name 'n' is not defined
    (Pdb) n
    > e:python3.6.3workspaceerr_pdb.py(3)<module>()
    -> print(10 / n)
    (Pdb) p n
    0
    (Pdb) p s
    '0'
    (Pdb) n
    ZeroDivisionError: division by zero
    > e:python3.6.3workspaceerr_pdb.py(3)<module>()
    -> print(10 / n)
    (Pdb) n
    --Return--
    > e:python3.6.3workspaceerr_pdb.py(3)<module>()->None
    -> print(10 / n)
    (Pdb) n
    ZeroDivisionError: division by zero
    > <string>(1)<module>()->None
    (Pdb) n
    --Return--
    > <string>(1)<module>()->None
    (Pdb) n
    Traceback (most recent call last):
      File "E:Python3.6.3libpdb.py", line 1667, in main
        pdb._runscript(mainpyfile)
      File "E:Python3.6.3libpdb.py", line 1548, in _runscript
        self.run(statement)
      File "E:Python3.6.3libdb.py", line 431, in run
        exec(cmd, globals, locals)
      File "<string>", line 1, in <module>
      File "e:python3.6.3workspaceerr_pdb.py", line 3, in <module>
        print(10 / n)
    ZeroDivisionError: division by zero
    Uncaught exception. Entering post mortem debugging
    Running 'cont' or 'step' will restart the program
    > e:python3.6.3workspaceerr_pdb.py(3)<module>()->None
    -> print(10 / n)
    (Pdb) q
    Post mortem debugger finished. The err_pdb.py will be restarted
    > e:python3.6.3workspaceerr_pdb.py(1)<module>()
    -> s = '0'
    (Pdb) n
    > e:python3.6.3workspaceerr_pdb.py(2)<module>()
    -> n = int(s)
    (Pdb) q
    PS E:Python3.6.3workspace>
    小写字母l,可以列出所有要执行的代码;
    
    n 命令表示单步执行代码;
    
    p 后面加上变量名,可以随时查看变量的值;
    
    在pdb模式中,对于还没有单步执行到的代码,相关的变量的变更是无效的;
    
    q 命令退出当前调试,进入重新从头开始调试,再次输入q,就会推出调试程序。
    
    这种方式的调试,有一个弊端,就是只能一步一步的执行下去,如果程序有很多行,岂不是累死。

      五、使用pdb.set_trace()

    #err_pdb.py
    import pdb
    
    s = '0'
    n = int(s)
    pdb.set_trace() #程序运行到这里会自动停止,等待命令
    print(10 / n)

      我们可以使用l、c、n、p、q等命令来控制和查看程序

    PS E:Python3.6.3workspace> python err_pdb.py
    > e:python3.6.3workspaceerr_pdb.py(7)<module>()
    -> print(10 / n)
    (Pdb) p s
    '0'
    (Pdb) l
      2     import pdb
      3
      4     s = '0'
      5     n = int(s)
      6     pdb.set_trace() #程序运行到这里会自动停止,等待命令
      7  -> print(10 / n)
    [EOF]
    (Pdb) n
    ZeroDivisionError: division by zero
    > e:python3.6.3workspaceerr_pdb.py(7)<module>()
    -> print(10 / n)
    (Pdb) c
    Traceback (most recent call last):
      File "err_pdb.py", line 7, in <module>
        print(10 / n)
    ZeroDivisionError: division by zero
  • 相关阅读:
    Windows 常见错误总结
    Windows 常用快捷方式
    【Linux】wget: command not found的两种解决方法
    【Linux】VirtualBox虚拟网络配置
    【Linux】启动Tomcat遇到Neither the JAVA_HOME nor the JRE_HOME environment variable is defined
    【REDIS】 redis-cli 命令
    【Charles】使用Charles时,抓不到包的情况。
    【Gradle】Downloading https://services.gradle.org/distributions/gradle-3.3-bin.zip 失败
    【LINUX】SHELL syntax error:unexpected end of file
    motan源码分析七:序列化
  • 原文地址:https://www.cnblogs.com/12345huangchun/p/10757720.html
Copyright © 2011-2022 走看看