python debugging

关注微信公众号(瓠悠笑软件部落),一起学习,一起摸鱼
huyouxiao.com

Raising Exceptions

可以用 raise statement 声明异常。写代码时,一个 raise statement 包含下列流程:

  • raise 关键字
  • Exception() 函数的调用
  • 一个 string 字面量,描述错误的信息。传给 Exception() 函数
>>> raise Exception('This is the error message.')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Exception: This is the error message.

如果没有 try 和 except statements 覆盖 raise 抛出的异常。程序会终止运行并抛出异常的错误信息。

Often it’s the code that calls the function, not the function itself, that knows how to handle an expection. So you will commonly see a raise statement inside a function and the try and except statements in the code calling the function.

#! /usr/bin/python3
def boxPrint(symbol, width, height):
    if len(symbol) != 1:
        raise Exception('Symbol must be a single character string.')
    if width <= 2:
        raise Exception('Width must be greater than 2.')
    if height <= 2:
        raise Exception('Height must be greater than 2.')

    print(symbol * width)
    for i in range(height - 2):
        print(symbol + (' ' * (width - 2)) + symbol)
    print(symbol * width)
for sym, w, h in (('*', 4, 4), ('0', 20, 5), ('x', 1, 30), ('88', 35, 35)):
    try:
        boxPrint(sym, w, h)
    except Exception as err:
        print('An exception happened: ' + str(err))

当传参数调用 boxPrint() 方法时,我们的 try/except 关键字将会处理无效的参数。这里程序使用 except Exception as err 来处理异常,如果方法 boxPrint() 返回了一个 Exception object . except statement 将会存储这个异常, 并把它命名为 err. 可以使用 str() 方法将 Exception object 转化成一个 string对象。方便用户查看。运行脚本,输出内容是:

****
*  *
*  *
****
00000000000000000000
0                  0
0                  0
0                  0
00000000000000000000
An exception happened: Width must be greater than 2.
An exception happened: Symbol must be a single character string.

使用try和except语句,您可以更优雅地处理错误,而不是让整个程序崩溃。

Getting the Traceback as a String

当Python遇到错误时,会产生 a treasure trove of error information, 称为 trackeback。 traceback 包括错误消息,导致错误的行的行号,以及该行的序列导致错误的函数调用。 这个调用序列称为 call stack.

#! /usr/bin/python3
def spam():
    bacon()

def bacon():
    raise Exception('This is the error message.')

spam()

输出内容:

Traceback (most recent call last):
  File "./errorExample.py", line 8, in <module>
    spam()
  File "./errorExample.py", line 3, in spam
    bacon()
  File "./errorExample.py", line 6, in bacon
    raise Exception('This is the error message.')
Exception: This is the error message.

traceback.format_exc()

如果想获取异常信息, 并把它写入日志文件里面。需要使用 traceback.format_exc()方法。使用前需要导入 traceback module.

huxing@huxing:~/my-repo/PythonLearn$ python
Python 3.5.2 (default, Nov 12 2018, 13:43:14) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import traceback
>>> try:
...     raise Exception('This is the error message.')
... except:
...     errorFile = open('errorInfo.txt', 'w')
...     errorFile.write(traceback.format_exc())
...     errorFile.close()
...     print('The traceback info was written to errorInfo.txt.')
... 
111
The traceback info was written to errorInfo.txt.

111 是 wrie()方法的返回值。有111个字符写进了文件里面。这里 traceback text 写进了 errorInfo.txt 文档中。

huxing@huxing:~/my-repo/PythonLearn$ cat errorInfo.txt 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
Exception: This is the error message.

Assertions

断言是一种健全性检查,以确保您的代码没有做出明显错误的事情这些健全性检查是通过 assert statements 实现的。如果健全性检查失败了,就会抛出 AssertionError exception. 从代码上看,一个 assert statement 包含以下部分:

  • assert 关键字
  • a condition (一个表达式,验证结果是 True 还是 False)
  • 一个冒号
  • 一个字符串,当 condition结果是 False 的时候显示
    在普通英语中, an assert statement 表示:" 我判定这个条件为真,如果不是,代码的某个地方肯定有一个bug." 不像 exceptions. 你的代码不能够通过 try和 except 处理 assert statements. 如果一个 assert 失败了,你的程序就会崩溃。
     Assertions 是编程人员的错误,不是开发人员的错误。

Using an Assertion in a Traffic Light Simulation

#! /usr/bin/python3
import logging
logging.basicConfig(level=logging.DEBUG, format=' %(asctime)s - %(levelname)s - %(message)s')
logging.debug('Start of program')

def factorial(n):
    logging.debug('Start of factorial(%s%%)' % (n))
    total = 1
    for i in range(1, n + 1):
        total *= i
        logging.debug('i is ' + str(i) + ', total is ' + str(total))
    logging.debug('End of factorial(%s%%)' % (n))
    return total

print(factorial(12))
logging.debug('End of  program')

#输出内容
 2019-03-08 18:33:14,307 - DEBUG - Start of program
 2019-03-08 18:33:14,307 - DEBUG - Start of factorial(12%)
 2019-03-08 18:33:14,307 - DEBUG - i is 1, total is 1
 2019-03-08 18:33:14,307 - DEBUG - i is 2, total is 2
 2019-03-08 18:33:14,307 - DEBUG - i is 3, total is 6
 2019-03-08 18:33:14,307 - DEBUG - i is 4, total is 24
 2019-03-08 18:33:14,308 - DEBUG - i is 5, total is 120
 2019-03-08 18:33:14,308 - DEBUG - i is 6, total is 720
 2019-03-08 18:33:14,308 - DEBUG - i is 7, total is 5040
 2019-03-08 18:33:14,308 - DEBUG - i is 8, total is 40320
 2019-03-08 18:33:14,308 - DEBUG - i is 9, total is 362880
 2019-03-08 18:33:14,308 - DEBUG - i is 10, total is 3628800
 2019-03-08 18:33:14,308 - DEBUG - i is 11, total is 39916800
 2019-03-08 18:33:14,308 - DEBUG - i is 12, total is 479001600
 2019-03-08 18:33:14,308 - DEBUG - End of factorial(12%)
479001600
 2019-03-08 18:33:14,309 - DEBUG - End of  program

Don’t debug with print()

用日志框架可以很方便的显示或者隐藏要答应的日志,隐藏的话,只需要添加: logging.disable(logging.CRITICAL) . 而如果用print打印日志,移除会修改多处。

Logging Levles in Python

  • DEBUG logging.debug() 最低等级,调试用
  • INFO logging.info()
  • WARNING logging.warning()
  • ERROR logging.error()
  • CRITICAL logging.critical() 最高等级,表示重大错误,会导致程序立即完全停止运行。
    有了日志等级,你就可以调整打印什么级别的日志。
Disabling Logging

logging.disable() 方法可以禁用日志。

Logging to a File

logging.basicConfig() 方法可以使用一个 filename 作为参数,将日志存储到文件里面

#! /usr/bin/python3
import logging
logging.basicConfig(filename='myProgramLog.txt', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
logging.critical('Critical error! Critical error!')
logging.error('Error! Error!')

运行后,会生成一个 myProgramLog.txt 的日志文件

IDLE’s Debugger

打开IDLE, 点击 Debug -> Debugger。选择 Stack, Locals, Source 和 Globals. 界面会显示所有的debug信息. 当 Debug Control window 出现的时候,显示“调试控制”窗口时,无论何时从文件编辑器运行程序,调试器都会暂停在第一条指令之前执行并显示以下内容:

  • 正在执行的那一行代码
  • 一组所有的局部变量和他们的值
  • 一组所有的全局变量和他们的值
    有五个键: Go, Step, Over, Out 和 Quit
  • Go 程序会继续往下执行直到 结束,或到 一个端点处 breakpoint. 如果想让程序继续正常往下执行,点击 Go 按钮.
  • Step 继续执行下一行代码。如果下一行代码是一个函数调用,debugger 会 step into 这个函数,并跳到这个函数里面的第一行代码。
  • Over 点击 Over 按钮将会执行剩下的代码,类似 Step 按钮,然而,如果下一行代码是一个函数调用,那么Over 按钮将会跳过(step over)这个函数里面的代码。函数里面的代码会不停顿地执行调。在函数返回的时候,debugger 将会暂停。
  • Out 点击Out button将会导致 debugger 全速执行当天函数剩下的代码。如果你 stepped info 一个函数调用,现在只想快速执行剩下的代码并且回到调用函数的地方。点击 Out 按钮就可以了。
  • Quit 如果想完全终止 debug 流程,并且不想执行剩下的代码,点击 Quit 按钮,Quit 按钮将会立即终止程序,如果你想正常运行你的程序,而不是debug。再选择一次 Debug -> Debugger就可以禁掉.
Debugging a Number Adding Program
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值