Python调试

10.1 抛出异常(raise)

	当Python试图执行无效代码时,则抛出异常。
	之前介绍过可使用 try-except 语句处理异常,使程序从预期的异常中恢复。
	现介绍使用 raise 语句在代码中抛出异常:“停止运行本函数,将程序执行到except语句”。
	
	使用raise语句,抛出异常,其包含:
	1. raise关键字;
	2. 对Exception函数的调用;
	3.传递给Eception函数的字符串(有用的出错信息)。
	若无 try-except 语句覆盖 raise 语句,程序会崩溃,显示异常出错信息。 通常为调用函数的代码知道如何处理异常,而非函数本身处理。故常见 raise 在函数中, try-except 在调用函数的代码中。 如:
# boxPrint.py
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(symbole * width)
	for i in range(height - 2):
		print(symbol + (' ' * (width - 2) )  + symbol)

for sym, w, h, in (('*', 4, 4), ('0', 20, 5), ('x', 1, 3), ('ZZ', 3, 3)):
	try:
		boxPrint(sym, w, h)
	except Exception as err:		# 将Exception对象保存在变量err中。
		print('An exception happened: ' + str(err))  # 将Exception传递给str(),转换为字符串,得到用户友好的信息

10.2 取得反向跟踪的字符串

	Python生成的错误信息,称为反向跟踪(含出错信息、导致错误的代码行号、导致错误的函数调用的序列(调用栈))。
	如#errorExample.py
def spam():
	bacon()
def bacon():
	raise Exception('This is the error message.')

spam()
若运行errorExample.py ,输出:
Traceback (most recent call last):
	File "errorExample.py", line 7, in<module> 
		spam()
	File "errorExample.py", line 2, in spam
		bacon()
	File "errorExample.py", line 5, in bacon
		raise Exception('This is the error message.')
Exception: This is the error message.
	通过反向跟踪,看到该错误发生在第5行,bacon(),bacon() 来自第2行spam(),spam()在第7行被调用。在从多次调用函数的程序中,调用栈可确定导致错误的调用。
	抛出的异常未处理,Python就会显示反向跟踪,调用traceback.format_exc(),可得到其字符串形式。
	将反向跟踪信息写入日志文件:
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.')
116
The traceback info was written to errorInfo.txt.
write()方法返回值是116,因为文件写入116个字符,反向跟踪文本被写入errorInfo.txt.

Traceback (most recent call last):
File “<pyshell#28>”, line 2, in
Exception: This is the error message.

10.3 断言(assert)

	断言,检查代码是否心智正常,确保其没有做明显错误的事情。
	assert语句执行心智正常的检查,若失败则抛出异常。包含:
		1.assert关键字;
		2.条件(True\False);
		3.逗号;
		4.条件为False时显示的字符串。
		例如: 
>>>podBayDoorStatus = 'open'
>>>assert podBayDoorStatus == 'open', 'The pod bay doore need to be "open".'
>>>podBayDoorStatus = 'I\'m sorry, Dave. I\'m afraid I can\'t do that.'
>>>assert podBayDoorStatus == 'open', 'The pod bay doors need to be "open".'
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    assert podBayDoorStatus == 'open', 'The pod bay doors need to be "open".'
AssertionError: The pod bay doors need to be "open".
"我断言这个条件为真,如果不为真,程序中什么地方就有一个缺陷。”
断言用于寻找错误的代码,try-except排除用户输入错误。
10.3.1 在交通灯模拟中使用断言
market_2nd = {'ns': 'green', 'ew': 'red'} #Market街和第2街路口
mission_16th = {'ns': 'red', 'ew': 'green'} # Mission街和第16街路口
def switchLights(stoplight):
	for key in stoplight.keys():
		if stoplight[key] == 'green':
			stoplight[key] = 'yellow'
		elif stoplight[key] = 'yellow':
			stoplight[key] = 'red'
		elif stoplight[key] == 'red':
			stoplight[key] = 'green'
switchLights(market_2nd)

在switchLights()中添加断言,确保至少有一个交通灯是红色。

--snip--
	assert 'red' in 'stopligh.values(), 'Neither light is red! ' + str(stoplight)
有此断言,程序会崩溃并提示:
Traceback (most recent call last):
  File "stopLight.py", line 13, in <module>
    switchLights(market_2nd)
  File "stopLight.py", line 11, in switchLights
    assert 'red' in stoplight.values(), 'Neither light is red!' + str(stoplight)
AssertionError: Neither light is red!{'ns': 'yellow', 'ew': 'green'}
断言检查心智正常与否,使程序及早结束,省去大量调试工作。

10.3.2 禁用断言
	在Python运行时传入-O选项,可以禁用断言。完成程序的编写和测试后,不再断言,以免减慢程序速度。
	如何启用-O选项?
	从终端窗口运行Python 时,在python 或python3 之后和.py 文件之前加上-O 开关。这将运行程序的优化版本,跳过断言检查。

10.4 日志
logging模块使创建自定义的消息记录。(记日志,可以理解程序中发生的事情,以及发生的顺序)

10.4.1 使用日志模块

import logging
logging.basicConfig(level=logging.DEBUG, format=' %(asctime)s - %(levelname)s- %(message)s')   # 打印一行信息。格式在basicConfig()中指定, 包括传递给debug()的消息。
logging.debug('Start of program')

def factorial(n):
	logging.debug('Start of factorial(%s%%)' %(n))
	total = 1
	for i in range(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(5))
logging.debug('End of program')
输出:
stopLight.py
  2020-03-16 21:27:27,860 - DEBUG- Start of program
 2020-03-16 21:27:27,860 - DEBUG- Start of factorial(5%)
 2020-03-16 21:27:27,861 - DEBUG- i is 0, total is 0
 2020-03-16 21:27:27,861 - DEBUG- i is 1, total is 0
 2020-03-16 21:27:27,861 - DEBUG- i is 2, total is 0
 2020-03-16 21:27:27,861 - DEBUG- i is 3, total is 0
 2020-03-16 21:27:27,861 - DEBUG- i is 4, total is 0
 2020-03-16 21:27:27,861 - DEBUG- i is 5, total is 0
 2020-03-16 21:27:27,861 - DEBUG- End of factorial(5%)
 2020-03-16 21:27:27,861 - DEBUG- End of program
0

Process finished with exit code 0
	可发现需更改为range(1, n+1)

10.4.2 不要用print()调试
print()给用户看的。logging给程序员看。

10.4.3 日志级别
在这里插入图片描述在这里插入图片描述向basicConfig()函数,level关键字传入不同级别的参数。

10.4.4 禁用日志

logging.disable()

10.4.5 日志记录到文件

logging.basicConfig(filename=‘myProgramlog.txt’, level=…)

10.5 IDLE的调试器
Debug->Debugger->Debug Control
勾选Stack、Locals、Source和Globals
1.Go 至终止或断点
2.Step 步入下一行(进入函数第一行)
3.Over 下一行(跨过函数)
4.Out 全速执行当前函数,至返回
5.Quit 立即终止
6.断点 set Breakpoint

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值