一、抛出异常
抛出异常:发现代码出现异常,停止运行,转而运行except中的语句。
raise用在函数中。
try和except语句调用函数的代码中。
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), ('O', 20, 5), ('x', 1, 3), ('ZZ', 3, 3)):
try:
boxPrint(sym, w, h)
except Exception as err:
print('An exception happened: ' + str(err))
二、取得反向跟踪的字符串
反向跟踪:Python遇到错误,就会生成一些错误信息,称为‘反向跟踪’
调用栈:反向跟踪包含了出错消息、导致该错误的代码行号,一级导致该错误的函数调用序列。
def spam():
bacon()
def bacon():
raise Exception('This is the error message')
spam()
Traceback (most recent call last):
File "D:\shy\testing.py", line 6, in <module>
spam()
File "D:\shy\testing.py", line 2, in spam
bacon()
File "D:\shy\testing.py", line 4, in bacon
raise Exception('This is the error message')
Exception: This is the error message
[Finished in 201ms]
traceback.format_exc()方法,可以得到报错形式的字符串形式。
只要抛出的异常没有被处理,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.')
三、断言
我将变量shy设置为stronger,然后添加了一个断言,确保shy变量一直是stronger,后面又不小心给变量shy赋了其他值,再使用这个断言进行判断,就可以发现哪里地方出错了。
1、在交通灯模拟中使用断言
模拟一下信号灯,十字路口,ns代表南北方向,初始灯为绿灯,ew代表东西,方向,初始为红灯。
定义一个函数: 转换信号灯颜色,然后断言一下,必须有一个路口的灯为红色,这个时候就报错了,提醒我们代码会有一种情况是两个路口的灯都不是红色,这就容易出事了。
crossroad={'ns':'green','ew':'red'}
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(crossroad)
这里最重要的一行就是最后一行AssertionError的报错信息,它告诉我们会有一种情况,两个路口都不是红灯。
2、禁用断言
在运行Python时传入-O选项,可以禁用断言。
四、日志
之前编写代码的时候,我们经常使用print()函数输出我们想要的代码运行结果,来判断代码是否出错,但是print()会将我们自己定义的调式信息也混杂在程序运行结果当中。这个时候就可以使用Python中的logging模块,创建自定义的消息记录。
1、使用日志模块
在程序顶部加上如下代码:
import logging
logging.basicConfig(level=logging.DEBUG, format=' %(asctime)s - %(levelname)s
- %(message)s')
编写一个求阶乘的代码,看一下效果:
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(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')
打印日志信息时,使用 logging.debug() 函数。这个 debug() 函数将调用 basicConfig(),打印一行信息。这行信息的格式是我们在 basicConfig()函数中指定的,并且包括我们传递给 debug() 的消息
2、不要用print()调式
3、日志级别
五种日志级别按从低到高排序:
DEBUG < INFO < WARNING < ERROR < CRITICAL
>>> import logging
>>> logging.basicConfig(level=logging.DEBUG, format=' %(asctime)s -
%(levelname)s - %(message)s')
>>> logging.debug('Some debugging details.')
2015-05-18 19:04:26,901 - DEBUG - Some debugging details.
>>> logging.info('The logging module is working.')
2015-05-18 19:04:35,569 - INFO - The logging module is working.
>>> logging.warning('An error message is about to be logged.')
2015-05-18 19:04:56,843 - WARNING - An error message is about to be logged.
>>> logging.error('An error has occurred.')
2015-05-18 19:05:07,737 - ERROR - An error has occurred.
>>> logging.critical('The program is unable to recover!')
2015-05-18 19:05:45,794 - CRITICAL - The program is unable to recover!
4、禁用日志
>>> import logging
>>> logging.basicConfig(level=logging.INFO, format=' %(asctime)s -
%(levelname)s - %(message)s')
>>> logging.critical('Critical error! Critical error!')
2015-05-22 11:10:48,054 - CRITICAL - Critical error! Critical error!
>>> logging.disable(logging.CRITICAL)
>>> logging.critical('Critical error! Critical error!')
>>> logging.error('Error! Error!')
logging.disable()将禁用它之后的所有消息,所以它之后的logging.critical()、logging.error()都不会输出任何消息了。
5、将日志记录到文件
import logging
logging.basicConfig(filename='myProgramLog.txt', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
五、IDLE的调试器
windows在Python安装目录下,双击下图该文件,打开idle
编写一个程序来试用下idle的调试器
print('enter the first number to add:')
first=input()
print('enter the second number to add:')
second=input()
print('enter the third number to add:')
third=input()
print('The sum is' + first + second + third)
运行一下发现程序出错:
现在就使用idle的调试器,来调试该程序:
点击over,程序执行到下一行 ,用over可以不用进入到print()函数的代码中。
继续点击over,执行input()函数调用,当我们还没有输入东西的时候,调式窗口中的按钮将被禁用。
输入5,并按回车,调试窗口按钮将重新启用。
重复,over,输入数字,三次。
可以看到,在全局变量的部分,第一、二、三个变量设置为字符串,而不是整型。当最后一行执行时,他们不是相加,而是拼接。
用调试器单步执行程序很有用,但也可能很慢。你常常希望程序正常运行,直到它到达特定的代码行。你可以使用断点,让调试器做到这一点
7、断点
编写演示程序:投掷1000次硬币,人头向上的次数。
import random
heads = 0
for i in range(1,1001):
if random.randint(0,1)==1:
heads=heads+1
if i==500:
print('halfway done')
print('heads came up ' + str(heads) +' times.')
要是用调试器运行这个程序,就必须点击几千次over按钮,程序才能结束。
如果只对程序运行到一半时heads的值感兴趣,可以在代码print('halfway done!')上设置断点。
不能在if语句上设置断点,因为if语句也会在每次循环的时候执行。
变黄色断点就设置好了
点over一次一次的太慢,
可以直接点go,程序执行到断点处,可以看到运行到500次时,人头向上的次数有277次
如果希望清除断点,在文件编辑器中该行代码上点击右键,并从菜单中选择 Clear Breakpoint。黄色高亮消失,以后调试器将不会在该行代码上中断。
六、小结
七、习题
2.编写一条 assert 语句,如果 eggs 和 bacon 包含的字符串彼此相同,而且不 论大小写如何,就触发 AssertionError(也就是说,'hello' 和 'hello' 被认为相同, 'goodbye' 和 'GOODbye' 也被认为相同)。
assert(eggs.lower()!=bacon.lower(),'ther are must same')
assert(False,'this is always triggers')