关注微信公众号(瓠悠笑软件部落),一起学习,一起摸鱼
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就可以禁掉.