【错误处理】

小结:遇到错误怎么办?

1、不理它。

2、捕获它,再抛出。

3、捕获并处理错误。

raise

不懂如何处理错误就直接抛出(raise),交由合适的层次处理,有时候需要自定义错误,但是通常使用Python内置的错误就可以了:

#!/usr/bin/env python3
# -*- coding: utf-8 -*- # 自定义的异常
class MyError(Exception):
pass # 抛出异常的函数
def f():
raise MyError('This is my error!') # 不处理,继续抛
def f2():
f() # 不处理,继续抛
def f3():
f2() print('hi1') # 被打印
f3()
print('hi2') # 不会被打印,因为程序因为出错而终止了

处理机的调用和函数调用的方向刚好相反,因为最终都没有人来处理这个错误,所以错误被一直上抛,直到被Python解释器捕获:

hi1
Traceback (most recent call last):
File "D:\labs\test.py", line 21, in <module>
File "D:\labs\test.py", line 18, in f3
File "D:\labs\test.py", line 14, in f2
File "D:\labs\test.py", line 10, in f
__main__.MyError: This is my error!

不懂如何处理错误的第二种方式是记录一下再继续抛出,这需要用到“try...except”:

# 自定义的异常
class MyError(Exception):
pass # 抛出异常的函数
def f():
raise MyError('This is my error!') # 不处理,继续抛
def f2():
f() # 不处理,继续抛
def f3():
f2() print('hi1') # 被打印 try:
f3()
except Exception as e:
print('...mark')
raise # 原样抛出
finally:
print('b') print('hi2') # 错误没被处理了,程序不再执行

输出:

hi1
...mark
b
Traceback (most recent call last):
File "D:\labs\test.py", line 23, in <module>
File "D:\labs\test.py", line 18, in f3
File "D:\labs\test.py", line 14, in f2
File "D:\labs\test.py", line 10, in f
__main__.MyError: This is my error!

(可以观察到finally是无论如何都会在最后被执行的!)

try...except

错误一般由底层代码抛出,通常是“他人的代码”,所以更经常写的是try...except别人抛出的错误。

那么如何自己来处理错误呢?当位于合适的层次的时候我们用“try...except”来处理错误:

print('hi1') # 被打印

try:
f3()
except Exception as e:
print('a:', e)
finally:
print('b') print('hi2') # 错误被处理了,程序继续执行

输出情况:

hi1
a: This is my error!
b
hi2

测试证明except 父类错误就可以捕获子类错误。

在try的内部一但raise了错误,如果有except语句将其捕获,那么try语句块的剩余语句是不会被执行的,因此try语句块要设定合适的范围,而不是一次try大量的语块:

class Error1(Exception):
pass try:
print('')
raise Error1('Error1')
print('') # 不被执行
print('') # 不被执行
except Exception as e:
print(e) print('continue execute')
1
Error1
continue execute

对于捕获多个错误的情况:

并不是多个错误都会被捕获,因为一旦raise了第一个错误,try语句块的程序就不会再继续执行了,所以同时抛出多个错误的情况是不存在的,书写多个except语句只是为了逐级排查最终捕获一个错误!

Python的except语句还可以加上else,如果没有错误将会执行else内的语句。

logging

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import logging class Error1(Exception):
pass try:
print('')
raise Error1('I make a mistake')
print('') # 不被执行
print('') # 不被执行
except Exception as e:
print('')
logging.exception(e)
print('') print('continue execute')
1
4
ERROR:root:I make a mistake
Traceback (most recent call last):
File "test.py", line 10, in <module>
raise Error1('I make a mistake')
Error1: I make a mistake
5
continue execute

今天遇到了一个问题卡了好一会儿:TabError: inconsistent use of tabs and spaces in indentation。原因是混用了空格和tab(可能是copy代码带来的)。最后删掉重输了一遍就解决了。

【调试】

debug的方法:

1、print

2、断言:print的升级版。

3、logging:既可以输出到console,也可以输出到文件、不打断程序执行。

在使用logging之前还需要在程序头添加一行配置:

import logging
logging.basicConfig(level=logging.WARNING)

level指定了记录信息的级别,分为DEBUG、INFO、WARNING、ERROR。当level指定为DEBUG,记录debug及以上的logging信息,当level指定为INFO,记录info及以上的logging信息,以此类推:

import logging
logging.basicConfig(level=logging.DEBUG) print(1)
logging.debug('debug:hi')
logging.info('info:hi')
logging.warning('warning:hi')
logging.error('error')
print(2)

输出:

1
DEBUG:root:debug:hi
INFO:root:info:hi
WARNING:root:warning:hi
ERROR:root:error
2

继续修改level的等级:

logging.basicConfig(level=logging.INFO)
1
INFO:root:info:hi
WARNING:root:warning:hi
ERROR:root:error
2

...

logging.basicConfig(level=logging.WARNING)
1
WARNING:root:warning:hi
ERROR:root:error
2

...

logging.basicConfig(level=logging.ERROR)
1
ERROR:root:error
2

4、pdb

在命令行下开启dubug模式(参数要加在文件名前面) :

$ python -m pdb test.py

输入n单步执行代码:

$ python -m pdb test.py
> d:\labs\test.py(3)<module>()
-> n = 0
(Pdb) n
> d:\labs\test.py(4)<module>()
-> print(1)
(Pdb) n
1
> d:\labs\test.py(5)<module>()
-> n = n + 1
(Pdb)

随时可以用 p 变量名查看变量:

> $ test.py(9)<module>()
-> n = n + 1
(Pdb) p n
2

使用q来退出。

最后,从某处开始debug的方法:

import pdb

print(1)
print(2)
pdb.set_trace() # 从这里开始进入debug模式。
print(3)
print(4)
print(5)

直接运行.py程序就可以了。

ps:一直执行n命令将循环运行程序。

【单元测试】

Q1:什么是单元测试?

Q2:如何进行单元测试?

A1:单元测试是指对一个模块、一个函数或者一个类来进行正确性检验的测试。

A2:例如我要检测自己写的sum()函数好不好用。

def sum(x, y):
return x + y

1、首先需要编写测试用例,这需要用到Python自带的unittest模块:

import unittest

from test import sum
class TestSum(unittest.TestCase):

    def test_func(self):
self.assertEqual(sum(1, 2), 3)
self.assertEqual(sum(1, -2), -1)
self.assertEqual(sum(100, -2), 98)
self.assertEqual(sum(1001, 110), 1111)

assertEqual是用于判定两个参数是否相等的函数,unittest模块中还有很多用于检测正确性的函数。 凡是test_xxx在测试的时候都会被运行。

import unittest

from test import sum

class TestSum(unittest.TestCase):

    def test_func(self):
self.assertEqual(sum(1, 2), 3)
self.assertEqual(sum(1, -2), 0)
self.assertEqual(sum(100, -2), 98)
self.assertEqual(sum(1001, 110), 1111) def test_func2(self):
self.assertEqual(sum(1, 2), 3)
self.assertEqual(sum(1, -2), 0)
self.assertEqual(sum(100, -2), 90)
self.assertEqual(sum(1001, 110), 1111) def test_func3(self):
self.assertEqual(sum(1, 2), 3)
self.assertEqual(sum(1, -2), -1)
self.assertEqual(sum(100, -2), 98)
self.assertEqual(sum(1001, 110), 1111) def test_func4(self):
print('hi~')
print('#$@#%@#$^%%#$^@@#$^&*')

2、运行测试用例:

$ python -m unittest sum_test.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s OK
$ python -m unittest sum_test.py
FF.hi~
#$@#%@#$^%%#$^@@#$^&*
.
======================================================================
FAIL: test_func (sum_test.TestSum)
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\labs\sum_test.py", line 9, in test_func
self.assertEqual(sum(1, -2), 0)
AssertionError: -1 != 0 ======================================================================
FAIL: test_func2 (sum_test.TestSum)
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\labs\sum_test.py", line 15, in test_func2
self.assertEqual(sum(1, -2), 0)
AssertionError: -1 != 0 ----------------------------------------------------------------------
Ran 4 tests in 0.000s FAILED (failures=2)

有时候可能会期待是不是抛出一些错误,可以这么写:

def test_attrerror(self):
d = Dict()
with self.assertRaises(AttributeError):
value = d.empty # raise AttributeError()

在测试用例中还可以添加setUp和tearDown函数,这两个函数分别在测试开始时和测试结束时被调用。

【文档测试】

1、搭建测试环境。

def sum(x, y):
''' test my sum funtion '''
return x + y if __name__ == '__main__':
import doctest
doctest.testmod()
$ python test.py

# 无输出

2、编写测试代码

def sum(x, y):
''' test my sum funtion >>> sum(2, 3)
5
>>> sum(1, 9)
10 '''
return x + y if __name__ == '__main__':
import doctest
doctest.testmod()

如果代码测试无误就不会有输出。

如果有错则有类似输出如下:

$ python test.py
**********************************************************************
File "test.py", line 8, in __main__.sum
Failed example:
sum(1, 9)
Expected:
9
Got:
10
**********************************************************************
1 items had failures:
1 of 2 in __main__.sum
***Test Failed*** 1 failures.

【Python】错误、调试和测试的更多相关文章

  1. 转 Python3 错误和异常/ Python学习之错误调试和测试

    ########sample 0 https://www.cnblogs.com/Simon-xm/p/4073028.html except: #捕获所有异常 except: <异常名> ...

  2. python错误调试print、assert、logging、pdb、pdb.set_trace()

    世界人都知道,程序总会有bug存在.复杂点的bug一般人不能一眼看出,这就一要一套调试程序的手段. 方法一:使用print()函数直接打印: >>> def foo(s): ... ...

  3. Python错误调试-raise、assert

    raise: raise语句手工引发一个异常:,这样做程序不会因异常而终止,而是运行报错 1 "raise" [expression ["," expressi ...

  4. Python错误、调试和测试

    try: print('try...') r = 10 / int('a') print('result:', r) except ValueError as e: print('ValueError ...

  5. Python:笔记(5)——错误、调试和测试

    Python:笔记(5)——错误.调试和测试 错误处理 1.TRY语句 这个和Java中的语法是及其相似的,catach换成except. 说明:同样,不管有没有错误,fianlly都会执行的! 补充 ...

  6. python 错误、调试、单元测试、文档测试

    错误分为程序的错误和由用户错误的输入引起的错误,此外还有因为各种各样意外的情况导致的错误,比如在磁盘满的时候写入.从网络爬取东西的时候,网络断了.这类错误称为异常 错误处理 参考链接:https:// ...

  7. 004-python面向对象,错误,调试和测试

    ---恢复内容开始--- 1.面向对象 面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作 ...

  8. python之错误调试

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

  9. Python错误处理和调试

    错误处理(try...except...finally...) try: print('try...') r = 10 / 0 print('result:', r) except ZeroDivis ...

  10. Python3 错误处理 和 测试

    try 让我们用一个例子来看看try的机制: try: print('try...') r = 10 / 0 except ZeroDivisionError as e: print('except: ...

随机推荐

  1. Xamarin绑定微信SDK 实现分享功能

    从开始做这一块的工作开始,就开始找各种的资料,最后还是老老实实的去看官方文档. 对于Xamarin.Android的绑定属于纯jar的绑定,这个难度较小,添加Bindings Library,将lib ...

  2. 用httpClient的PostMethot频繁发送数据,抛出Too many open files

    在工作过程中,用httpclient去压测一个web api,发现压一小段时间就出现了Too many open files.实际上,HttpClient建立Socket时 ,post.release ...

  3. ajax请求步骤

    ajax步骤:第一步:创建xmlhttprequest对象,var xmlhttp = new XMLHttpRequest(); XMLHttpRequest对象和服务器交换数据.第二步:使用xml ...

  4. 2017 Multi-University Training Contest - Team 6—HDU6098&&HDU6106&&HDU6103

    HDU6098 Inversion 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6098 题目意思:题目很短,给出一个数组,下标从1开始,现在输出一个 ...

  5. POJ3660 传递闭包———floyd算法

    POJ3660 Cow Contest 题目链接:http://poj.org/problem?id=3660 题意:农名约翰有些奶牛,约翰通过让他们决斗来决定他们的排名,约翰让这些奶牛一对一打完一定 ...

  6. 用Python爬虫爬取广州大学教务系统的成绩(内网访问)

    用Python爬虫爬取广州大学教务系统的成绩(内网访问) 在进行爬取前,首先要了解: 1.什么是CSS选择器? 每一条css样式定义由两部分组成,形式如下: [code] 选择器{样式} [/code ...

  7. git学习——<四>git版本管理

    一.git版本管理的优势 都说git比svn强大,强大在哪呢? 首先,从部署上说:svn.cvs都是集中式的,一台服务器上部署服务,所有客户端编写的代码都要提交到该服务器上.git是分布式的,所有人都 ...

  8. Python并行编程(五):线程同步之信号量

    1.基本概念 信号量是由操作系统管理的一种抽象数据类型,用于在多线程中同步对共享资源的使用.本质上说,信号量是一个内部数据,用于标明当前的共享资源可以有多少并发读取. 同样在threading中,信号 ...

  9. openssl生成证书server.key server.crt

    Key是私用秘钥,通常是RSA算法 Csr是证书请求文件,用于申请证书.在制作csr文件时,必须使用自己的私钥来签署申,还可以设定一个密钥. crt是CA认证后的证书文,签署人用自己的key给你签署凭 ...

  10. 不再依赖A*,利用C++编写全新寻路算法

    一,说在前面的话 大概在半年前,看见一到信息竞赛题:在任意方格阵中设置障碍物,确定起始点后,求这两点之间路径.当时觉得蛮有意思的,但是没有时间去做,今天花了两个小时来实现它.据说有一个更高级的寻路算法 ...