大师兄的Python学习笔记(七): re包与正则表达式
大师兄的Python学习笔记(九): logging模块与日志
一、语法错误和异常
1.语法错误
- 语法错误通常是因为人为导致的错误。
- 语法错误可以通过人为避免。
- 遇到语法错误时,编译器将不执行代码,而直接指出语法错误行。
>>>print( # 这里少了半个括号
File "", line 1
print(
^
SyntaxError: unexpected EOF while parsing
2.异常
- 异常是在语法正确的情况下出现的问题。
- 有些异常时无法避免的。
- 当异常发生时,如果没有处理,程序可能会在异常处终止,并将异常信息抛出到console中。
- 异常分为内置异常和自定义异常。
>>>print(1/0) # 从语法上来说是正确的,但是1/0在数学上是错误的
ZeroDivisionError Traceback (most recent call last)
in
----> 1 print(1/0)
ZeroDivisionError: division by zero
3.异常类
- 异常在Python中是类,可以用类的方法处理和使用。
- 既然是类,也具备实例化、继承等属性。
3.1 基类
- 这些异常类属于异常的基类。
- 异常类层级结构如下(在Python官方文档上添加了EnvironmentError):
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StopAsyncIteration
+-- ArithmeticError
| +-- FloatingPointError
| +-- OverflowError
| +-- ZeroDivisionError
+-- AssertionError
+-- AttributeError
+-- BufferError
+-- EOFError
+-- ImportError
| +-- ModuleNotFoundError
+-- LookupError
| +-- IndexError
| +-- KeyError
+-- MemoryError
+-- NameError
| +-- UnboundLocalError
+-- OSError
| +-- BlockingIOError
| +-- ChildProcessError
| +-- ConnectionError
| | +-- BrokenPipeError
| | +-- ConnectionAbortedError
| | +-- ConnectionRefusedError
| | +-- ConnectionResetError
| +-- FileExistsError
| +-- FileNotFoundError
| +-- InterruptedError
| +-- IsADirectoryError
| +-- NotADirectoryError
| +-- PermissionError
| +-- ProcessLookupError
| +-- TimeoutError
+-- ReferenceError
+-- RuntimeError
| +-- NotImplementedError
| +-- RecursionError
+-- SyntaxError
| +-- IndentationError
| +-- TabError
+-- SystemError
+-- TypeError
+-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- EnvironmentError
| IOError
| +-- WindowsError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning
+-- ResourceWarning
1)BaseException
- 是以下所有内置异常的基类。
>>>try: >>> raise ValueError('valueError occured') # 手动抛出了一个valueError异常 >>>except BaseException as e: # 用BaseException成功拦截 >>> print(e) valueError occured
2)Exception
- 是BaseException的子类。
- 所有内置的非系统退出类异常都派生自此类。
- 所有用户自定义异常也应当派生自此类。
- 是3),4),5)的父类。
>>>isinstance(Exception(),BaseException) # BaseException是Exception的父类 True >>>try: >>> print(1/0) >>>except Exception as e: >>> print(e) division by zero
3)ArithmeticError
- 所有算术类错误而引发的内置异常派生自此类。
>>>isinstance(ArithmeticError(),Exception) True >>>try: >>> print(1/0) >>>except ArithmeticError as e: >>> print(e) division by zero
4)BufferError
- 所有缓冲区相关的异常派生自此类。
>>>isinstance(BufferError(),Exception) True >>>try: >>> raise BufferError('BufferError occered!') >>>except BufferError as e: >>> print(e) BufferError occered!
5)LookupError
- 派生所有映射或序列所使用的键或索引无效时引发的异常。
>>>isinstance(LookupError(),Exception) True >>>l = [1,2,3] >>>try: >>> print(l[4]) # l的索引只到2 >>>except LookupError as e: >>> print(e) >>>list index out of range
3.2 常用异常
6)AssertionError
- Exception的子类。
- assert语句失败时引发的异常。
>>>i = 1 >>>assert i > 5 # 这里引发异常 AssertionError Traceback (most recent call last)
in 1 i = 1 ----> 2 assert i > 5 3 AssertionError: 7)AttributeError
- Exception的子类。
- 当属性引用或赋值失败时被引发。
>>>class test(): >>> pass >>>t = test() >>>print(t.a) # object t并没有属性a AttributeError Traceback (most recent call last)
in 2 pass 3 t = test() ----> 4 print(t.a) AttributeError: 'test' object has no attribute 'a' 8)EOFError
- 当 input() 函数未读取任何数据即达到文件结束条件 (EOF) 时引发。
- 通常是在Linux系统下Ctrl+D引起的。
>>> input('请输入内容:\n') # 运行后输入Ctrl+D退出 请输入内容: Traceback (most recent call last): File "
", line 1, in EOFError 9)GeneratorExit
- 直接继承自BaseException。
- 当一个迭代器或携程被关闭时引发。
- 其实并不能算错一个错误。
- 系统会自动处理。
>>>def mygen(): >>> try: >>> yield 1 >>> except GeneratorExit: >>> print ("GeneratorExit occured!") >>>gen = mygen() >>>del gen GeneratorExit occured!
10)ImportError
- Exception的子类。
- 加载模块出错时引发。
>>>from os import somethingnotexist ImportError Traceback (most recent call last)
in ----> 1 from os import somethingnotexist ImportError: cannot import name 'somethingnotexist' from 'os' (d:\python3.7\lib\os.py) 11)ModuleNotFoundError
- ImportError的子类。
- 当使用import一个模块,但无法被定位时引发。
>>>import somethingnotexist ModuleNotFoundError Traceback (most recent call last)
in ----> 1 import somethingnotexist ModuleNotFoundError: No module named 'somethingnotexist' 12)IndexError
- lookupError的子类。
- 当序列抽取超出范围时将被引发。
>>>l = [1,2,3] >>>print(l[3]) # l索引最大到2 IndexError Traceback (most recent call last)
in 1 l = [1,2,3] ----> 2 print(l[3]) IndexError: list index out of range 13)KeyError
- lookupError的子类。
- 字典中查找一个不存在的关键字时触发。
>>>d = dict() # 一个空字典 >>>d['a'] KeyError Traceback (most recent call last)
in 1 d = dict() ----> 2 d['a'] KeyError: 'a' 14)KeyboardInterrupt
- BaseException的子类,不会被Exception捕获。
- 当用户按下中断键时触发。(比如ctrl+C)
>>> try: >>> input('wait...') >>> except KeyboardInterrupt as e: >>> print('KeyboardInterrupt!\n') wait... #ctrl+c中断 KeyboardInterrupt!
15)MemoryError
- Exception的子类。
- 当内存超出时引发。
16)NameError
- Exception的子类。
- 当某个局部或全局名称未找到时将被引发。
>>>print(somethingnotexist) NameError Traceback (most recent call last)
in ----> 1 print(somethingnotexist) NameError: name 'somethingnotexist' is not defined 17)NotImplementedError
- RuntimeError的子类。
- 当抽象类的方法没有被实现时触发。
>>>class Animal(): >>> def bart(self): >>> raise NotImplementedError('我没有被实现!') # 方法没有被子类实现时抛出错误 >>>class Dog(Animal): >>> pass >>>dog = Dog() >>>dog.bart() NotImplementedError Traceback (most recent call last)
in 7 8 dog = Dog() ----> 9 dog.bart() in bart(self) 1 class Animal(): 2 def bart(self): ----> 3 raise NotImplementedError('我没有被实现!') 4 5 class Dog(Animal): NotImplementedError: 我没有被实现! 18)OSError(
)
- Exception的子类。
- 当一个系统函数返回系统相关的错误时将被引发。
- 通常返回的是OSError的子类。
>>>os.rmdir('somethingnotexist') # FileNotFoundError是OSError的子类 FileNotFoundError Traceback (most recent call last)
in ----> 1 os.rmdir('somethingnotexist') FileNotFoundError: [WinError 2] 系统找不到指定的文件。: 'somethingnotexist' 19)OverflowError
- ArithmeticError的子类。
- 当算术运算的结果大到无法表示时将被引发。
20)RecursionError
- RuntimeError的子类。
- 递归超过最大深度时引发。
>>>def A(): # 一个无限的递归函数 >>> print('test') >>> A() >>>A() ... test test --------------------------------------------------------------------------- RecursionError Traceback (most recent call last)
in 2 print('test') 3 A() ----> 4 A() in A() 1 def A(): 2 print('test') ----> 3 A() 4 A() ... last 1 frames repeated, from the frame below ... in A() 1 def A(): 2 print('test') ----> 3 A() 4 A() RecursionError: maximum recursion depth exceeded while calling a Python object 21)ReferenceError
- Exception的子类。
- 使用weakref.proxy()函数创建的弱引用试图访问已经垃圾回收了的对象时触发。
22)RuntimeError
- Exception的子类。
- 当检测到一个不属于任何其他类别的错误时将被引发。
>>>def countResult(n): >>> if n>0: >>> return 'result>0' >>> elif n<0: >>> return 'result<0' >>> else: >>> try: >>> raise RuntimeError('no result!') # 抛出异常 >>> except Exception as e: >>> return e >>>print(countResult(0)) no result!
23)StopIteration
- Exception的子类。
- 当迭代器里没有更多值时触发。
>>>it = iter([1,2,3]) # 创建一个简单的迭代器 >>>print(next(it)) >>>print(next(it)) >>>print(next(it)) >>>print(next(it)) # it中只有3个元素 1 2 3 --------------------------------------------------------------------------- StopIteration Traceback (most recent call last)
in 3 print(next(it)) 4 print(next(it)) ----> 5 print(next(it)) StopIteration: 24)StopAsyncIteration
- Exception的子类。
- 必须通过异步迭代器对象的__anext__()方法引发以停止迭代
# test()文件 >>>import asyncio >>>async def genfunc(): >>> yield 1 >>> yield 2 >>>gen = genfunc() >>>async def start(): >>> assert gen.__aiter__() is gen >>> assert await gen.__anext__() == 1 >>> assert await gen.__anext__() == 2 >>> await gen.__anext__() # This line will raise StopAsyncIteration. >>>if __name__ == '__main__': >>> asyncio.run(start()) >>>python test.py # 执行test文件 Traceback (most recent call last): File "G:/WeMud_new/test.py", line 15, in
asyncio.run(start()) File "D:\Python3.7\lib\asyncio\runners.py", line 43, in run return loop.run_until_complete(main) File "D:\Python3.7\lib\asyncio\base_events.py", line 584, in run_until_complete return future.result() File "G:/WeMud_new/test.py", line 12, in start await gen.__anext__() # This line will raise StopAsyncIteration. StopAsyncIteration 25)SyntaxError
- Exception的子类。
- 语法错误引发。
>>>print( # 这里少了半个括号 File "
", line 1 print( ^ SyntaxError: unexpected EOF while parsing 26)IndentationError
- SyntaxError的子类。
- 缩进错误时触发。
>>>def func(): >>>return # 这里没有按规范缩进 File "
", line 2 return ^ IndentationError: expected an indented block 27)TabError
IndentationError的子类。
- 当缩进制表符(tab)和空格混用时触发。(如果用开发工具比如pycharm可能会自动修复)
>>> def func(): >>> print(1) # 缩进一个空格 >>> return # 缩进一个tab File "
", line 3 return ^ TabError: inconsistent use of tabs and spaces in indentation 28)SystemError
- Exception的子类。
- 当解释器发现内部错误,但情况看起来尚未严重到要放弃所有希望时将被引发。
29)SystemExit
- BaseException的子类。
- 当调用sys.exit()时触发。
>>>import sys >>>try: >>> sys.exit() >>>except SystemExit as e: >>> print('SystemExit occured!') SystemExit occured!
30)TypeError
- Exception的子类。
- 当一个操作或函数被应用于类型不适当的对象时将被引发。
>>>s = 'Hello World!' >>>s += 1 # 字符串不能和数字相加 TypeError Traceback (most recent call last)
in 1 s = 'Hello World!' ----> 2 s += 1 TypeError: can only concatenate str (not "int") to str 31)UnboundLocalError
- NameError的子类。
- 当变量被调用,但未被赋值时触发。
>>>def test(): >>> a += 1 >>> return a >>>test() UnboundLocalError Traceback (most recent call last)
in 3 return a 4 ----> 5 test() in test() 1 def test(): ----> 2 a += 1 3 return a 4 5 test() UnboundLocalError: local variable 'a' referenced before assignment 32)UnicodeError
- ValueError的子类。
- 当发生与 Unicode 相关的编码或解码错误时将被引发。
33)UnicodeEncodeError
- UnicodeError的子类。
- 当在编码过程中发生与 Unicode 相关的错误时将被引发。
>>>b = u'汉字'.encode('ascii') #ascii无法解码unicode中文 UnicodeEncodeError Traceback (most recent call last)
in ----> 1 b = u'汉字'.encode('ascii') UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128) 34)UnicodeDecodeError
- UnicodeError的子类。
- 当在解码过程中发生与 Unicode 相关的错误时将被引发。
>>>b = u'汉字'.encode('utf-8') >>>b.decode('ascii') # ascii编码无法解码汉字 UnicodeDecodeError Traceback (most recent call last)
in 1 b = u'汉字'.encode('utf-8') ----> 2 b.decode('ascii') UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6 in position 0: ordinal not in range(128) 35)UnicodeTranslateError
- UnicodeError的子类。
- 在转写过程中发生与 Unicode 相关的错误时将被引发。
36)ValueError
- Exception的子类。
- 当操作或函数接收到具有正确类型但值不适合的参数,并且情况不能用更精确的异常。
>>>for k,v in 'Hello World': # 没有足够的值便利 >>> print(k) ValueError Traceback (most recent call last)
in ----> 1 for k,v in 'Hello World': 2 print(k) ValueError: not enough values to unpack (expected 2, got 1) 37)ZeroDivisionError
- ArithmeticError的子类。
- 当除法或取余运算的第二个参数为零时将被引发。
>>>1/0 ZeroDivisionError Traceback (most recent call last)
in ----> 1 1/0 ZeroDivisionError: division by zero 38)EnvironmentError
- Exception的子类。
- 操作系统错误的基类。
>>>isinstance(EnvironmentError(),Exception) True
39)IOError
- EnvironmentError的子类。
- 输入/输出操作失败
40)WindowsError
- IOError的子类。
- windows系统调用失败。
- 只能在windows操作系统使用。
3.3 OS异常
- 均为OSError的子类。
41)BlockingIOError
- 当一个操作会被某个设置为非阻塞操作的对象(例如套接字)所阻塞时将被引发。
>>>import os,sys >>> while True: # 一个不断进程分叉的死循环,最终资源不足导致BlockIOError >>> pid = os.fork() # 进程分叉 >>> if pid==0: # 父进程 >>> sys.exit() >>> elif pid>0: # 子进程 >>> pass >>> else: >>> sys.exit() Traceback (most recent call last): File "
", line 2, in BlockingIOError: [Errno 11] Resource temporarily unavailable 42)ChildProcessError
- 当一个子进程的失败时被引发。
43)ConnectionError
- 连接相关异常的基类。
- 由于网络的不确定性,在爬虫时常见。
44)BrokenPipeError
- ConnectionError的子类。
- 当试图写入另一端已被关闭的管道,或是试图写入已关闭写入的套接字时将被引发。
# test.py文件 >>>import sys >>>for line in sys.stdin: # 从标准输入导出标准输出 >>> print(line) # linux控制台 >ps -elf | python testexp.py | head -n 10 Exception ignored in: <_io.TextIOWrapper name='
' mode='w' encoding='UTF-8'> BrokenPipeError: [Errno 32] Broken pipe 45)ConnectionAbortedError
- ConnectionError的子类。
- 当连接尝试被对端中止时将被引发。
46)ConnectionRefusedError
- ConnectionError的子类。
- 当连接尝试被对端拒绝时将被引发。
47)ConnectionResetError
- ConnectionError的子类。
- 当连接被对端重置时将被引发。
48)FileExistsError
- 当试图创建一个已存在的文件或目录时将被引发。
>>>os.makedirs(os.path.curdir) # 创建当前的目录...是不是很蠢 FileExistsError Traceback (most recent call last)
in ----> 1 os.makedirs(os.path.curdir) 49)FileNotFoundError
- 当所请求的文件或目录不存在时将被引发。
>>>open('notexist.py') # notexist.py并不存在 FileNotFoundError Traceback (most recent call last)
in 1 import os ----> 2 open('notexist.py') FileNotFoundError: [Errno 2] No such file or directory: 'notexist.py' 50)InterruptedError
- 系统调用被中断时触发。
51)IsADirectoryError
- 当请求对一个目录执行文件操作时触发。
>>> import os >>> os.mkdir('newdir') # 创建一个新路径 >>> open('newdir','r') # 以打开文件的方式打开路径名 Traceback (most recent call last): File "
", line 1, in IsADirectoryError: [Errno 21] Is a directory: 'newdir' 52)NotADirectoryError
- 当请求对一个非目录对象执行目录操作时触发。
>>> import os >>> os.chdir('test.txt') Traceback (most recent call last): File "
", line 1, in NotADirectoryError: [Errno 20] Not a directory: 'test.txt' 53)PermissionError
- 当在没有足够操作权限的情况下试图执行某个操作时将被引发 。
>>>with open('d:\wemud','r') as f: # 没有给予d盘权限的情况下 >>> print(f) PermissionError Traceback (most recent call last)
in ----> 1 with open('d:\wemud','r') as f: 2 print(f) PermissionError: [Errno 13] Permission denied: 'd:\\wemud' 54)ProcessLookupError
- 当给定的进程不存在时将被引发。
>>> os.kill(123456,0) # 一个不存在的进程 Traceback (most recent call last): File "
", line 1, in ProcessLookupError: [Errno 3] No such process 55)TimeoutError
- 当一个系统函数发生系统级超时的情况下将被引发。
3.4 警告
- 警告会弹出异常信息,但不会停止程序。
- 警告可以用来自定义异常,提醒用户注意事项。
56)Warning
- Exception的子类。
- 所有警告类别的基类
>>>isinstance(Warning(),Exception) True
57)UserWarning
- Warning的子类。
- 用户代码所产生警告的基类。
>>>isinstance(UserWarning(),Warning) True
58)DeprecationWarning
- Warning的子类。
- 通常用来警告特征已弃用。
>>>from openpyxl import Workbook >>>wb = Workbook() >>>wb.create_sheet("Mysheet") >>>sheet = wb.get_sheet_by_name('Mysheet') # 这是一个过期的方法 d:\ProgramData\Anaconda3\lib\site-packages\ipykernel_launcher.py:4: DeprecationWarning: Call to >deprecated function get_sheet_by_name (Use wb[sheetname]). after removing the cwd from sys.path.
59)PendingDeprecationWarning
- Warning的子类。
- 对于已过时并预计在未来弃用,但目前尚未弃用的特性相关警告的基类。
- 这个类很少用,推荐使用DeprecationWarning。
60)SyntaxWarning
- Warning的子类。
- 与模糊的语法相关的警告的基类。
61)RuntimeWarning
- Warning的子类。
- 与模糊的运行时行为相关的警告的基类。
62)FutureWarning
- Warning的子类。
- 已弃用特性相关警告的基类。
63)ImportWarning
- Warning的子类。
- 与在模块导入中可能的错误相关的警告的基类。
64)UnicodeWarning
- Warning的子类。
- 与 Unicode 相关的警告的基类。
65)BytesWarning
- Warning的子类。
- 与 bytes和bytearray相关的警告的基类。
66)ResourceWarning
- Warning的子类。
- 与资源使用相关的警告的基类。 会被默认的警告过滤器忽略。
二、异常处理
- 不能保证所有问题都被解决。
- 用于保证程序在最坏的情况下,问题被妥善处理。
- 异常处理可以让代码更健壮。
4. 异常处理的语法
4.1 try .. except 语句
- 用于捕获并处理异常。
- 如果异常被捕获,则不会造成程序中断。
- 完整结构式:
try:
<尝试某个操作,如果发生异常则进入except捕获流程>
except <异常1>:
<捕获某个异常,并运行这里的内容>
except <异常2>:
<捕获某个异常,并运行这里的内容>
else:
<如果没有异常捕获,则运行这里的内容>
finally:
<不管有没有异常捕获,都会运行这里的内容>
1)try .. except...
- try ... except...必须成对出现。
- except可以有多个,如果发生多个异常将捕获第一个发生的异常。
- except捕获的异常应该是子类在前,父类在后,否则子类有可能捕获不到。
- except可以用
as语句
将异常类实例化。>>>try: >>> abc # NameError >>> 1/0 # ZeroDivisionError >>> import notexist # importError >>>except NameError as e: # 捕获了第一个发生的异常,先捕获子类异常。 >>> print('NameError occured: {e}'.format(e=e)) >>>except ZeroDivisionError as e: # 通过as语句将Exception实例化。 >>> print('ZeroDivisionError occured: {e}'.format(e=e)) >>>except Exception as e: # 父类异常放在后面 >>> print('Exception occured: {e}'.format(e=e)) NameError occured: name 'abc' is not defined
2)try .. except...else...
- 如果没有异常被except捕获,并且try中的内容正常执行,则执行else中的内容。
- else不是必选项。
>>>try: >>> print('some strong code') >>>except NameError as e: >>> print('NameError occured: {e}'.format(e=e)) >>>except ZeroDivisionError as e: >>> print('ZeroDivisionError occured: {e}'.format(e=e)) >>>except Exception as e: >>> print('Exception occured: {e}'.format(e=e)) >>>else: # 没有异常发生,所以执行else中的内容 >>> print('flex muscle!') some strong code flex muscle!
3)try .. except...finally...
- 不管有没有异常捕获,都会执行finally中的内容。
- finally不是必选项。
>>>try: >>> print('some code') >>> 1/0 # bug发生 >>>except (NameError,ZeroDivisionError) as e: # 捕获异常 >>> print('ZeroDivisionError occured: {e}'.format(e=e)) >>>except Exception as e: >>> print('Exception occured: {e}'.format(e=e)) >>>else: # 有bug所以不会运行else >>> print('flex muscle!') >>>finally: # 不管怎样都会执行finally >>> print('what so ever') some code ZeroDivisionError occured: division by zero what so ever
4.2 raise 语句
- 可以手动抛出某个异常
- 语法是raise <异常>
>>>try:
>>> raise DeprecationWarning('Python2快要停止维护啦!')
>>>except DeprecationWarning as e:
>>> print(e)
Python2快要停止维护啦!
三、自定义异常
- 自定义异常一般通过继承系统异常类的方式创建。
- 一般系统自带异常就够用了,除非有特殊需求。
- 如果是raise异常,推荐自定义异常。
>>>class QQWarning(RuntimeWarning): # 新的警告继承自RuntimeWarning
>>> def __init__(self, *arg):
>>> self.args = arg
>>> self.bart()
>>> def bart(self):
>>> print('嗷嗷嗷!')
>>>try:
>>> raise QQWarning('QQ在警告你!')
>>>except QQWarning as e:
>>> print(e)
嗷嗷嗷!
QQ在警告你!
参考资料
- https://blog.csdn.net/u010138758/article/details/80152151 J-Ombudsman
- https://www.cnblogs.com/zhuluqing/p/8832205.html moisiet
- https://www.runoob.com 菜鸟教程
- http://www.tulingxueyuan.com/ 北京图灵学院
- http://www.imooc.com/article/19184?block_id=tuijian_wz#child_5_1 两点水
- https://blog.csdn.net/weixin_44213550/article/details/91346411 python老菜鸟
- https://realpython.com/python-string-formatting/ Dan Bader
- https://www.liaoxuefeng.com/ 廖雪峰
- https://blog.csdn.net/Gnewocean/article/details/85319590 新海说
- 《Python学习手册》Mark Lutz
- 《Python编程 从入门到实践》Eric Matthes
本文作者:大师兄(superkmi)