Python-错误和异常总结(内置异常、assert、抛出异常、异常捕获与处理)_cannot fit ‘int‘ into an index-sized integer

写在最后

在结束之际,我想重申的是,学习并非如攀登险峻高峰,而是如滴水穿石般的持久累积。尤其当我们步入工作岗位之后,持之以恒的学习变得愈发不易,如同在茫茫大海中独自划舟,稍有松懈便可能被巨浪吞噬。然而,对于我们程序员而言,学习是生存之本,是我们在激烈市场竞争中立于不败之地的关键。一旦停止学习,我们便如同逆水行舟,不进则退,终将被时代的洪流所淘汰。因此,不断汲取新知识,不仅是对自己的提升,更是对自己的一份珍贵投资。让我们不断磨砺自己,与时代共同进步,书写属于我们的辉煌篇章。

需要完整版PDF学习资源私我

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以点击这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!


简介

如果你编写过C++程序,相信你应该有过被“烫烫烫”、“屯屯屯”支配的恐惧。作为程序员,我们每天就是在写代码bug,然后改bug。通过本文你可以看懂自己程序发生的错误或异常,如何自己定义异常,如何处理/避免异常。你需要注意是什么引起了某个异常,在编程时进行避免或处理。Python官方文档将语法错误单独拿了出来,称为错误,其它的称为异常。它可能考虑的是语法错误是在运行前,而其它是在运行时,本文仍把语法错误作为异常,按照类层次结构进行展开。如果要我分类的话,我会分为三类:

  • 运行前——编译出错,语法错误
  • 运行时——运行出错,逻辑错误
  • 运行后——结果出错,逻辑错误

比如,有时刚编程的小白可能会写 if x=0 : …,其实他的本意是判断x是否等于0,而不是赋值,由于少敲了一个等于号,导致程序结果出错,也有可能转为运行时出错。对于逻辑错误,就涉及到代码规范、代码优化以及设计模式等内容,代码规范本专栏有,其他的还没写。

异常-Exception

即使语句或表达式在语法上是正确的,但在尝试执行时,它仍可能会引发错误。 在执行时检测到的错误被称为异常,异常不一定会导致严重后果。

异常分为两个阶段,第一个阶段是发现错误后引发异常,这个动作也可以成为触发抛出等。第二个阶段就是异常处理。

内置异常

内置异常类层级结构:

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
      +-- Warning
           +-- DeprecationWarning
           +-- PendingDeprecationWarning
           +-- RuntimeWarning
           +-- SyntaxWarning
           +-- UserWarning
           +-- FutureWarning
           +-- ImportWarning
           +-- UnicodeWarning
           +-- BytesWarning
           +-- ResourceWarning

上面是官方给的,我们可以自己写一个函数来展示类层级结构

def classtree(cls, indent=0):
    print('+'+'-' * (indent-1), cls.__name__)
    for subcls in cls.__subclasses__():
        classtree(subcls, indent + 3)


classtree(BaseException)
基类

基类

名称描述
BaseException所有内置异常的基类。 它不应该被用户自定义类直接继承。
Exception所有内置的非系统退出类异常都派生自此类。 所有用户自定义异常也应当派生自此类。
ArithmeticError此基类用于派生针对各种算术类错误而引发的内置异常。
BufferError当与缓冲区相关的操作无法执行时将被引发
LookupError此基类用于派生当映射或序列所使用的键或索引无效时引发的异常

具体异常

SystemExit

此异常由sys.exit()函数引发。 它继承自BaseException而不是Exception以确保不会被处理Exception的代码意外捕获。 这允许此异常正确地向上传播并导致解释器退出。 如果它未被处理,则Python 解释器就将退出;不会打印任何栈回溯信息。

import sys


print('lady')
exit(0)
print('killer')

结果:

lady

KeyboardInterrupt

当用户按下中断键 (通常为 Control-C 或 Delete) 时将被引发。

while True:
    print()

运行后按Ctrl+C,结果:

Traceback (most recent call last):
  File “learnException.py”, line 17, in
    print()
KeyboardInterrupt

GeneratorExit

它直接继承自BaseException而不是Exception,因为从技术上来说它并不是一个错误

---------------------------接下来是可以被捕获的-------------------------------

StopIteration

内置函数next()和iterator的__next__()方法所引发,用来表示该迭代器不能产生下一项。

def myGenerator():
    try:
        yield 1
        yield 2
    except GeneratorExit:
        print('GeneratorExit happened')


gen = myGenerator()
next(gen)
next(gen)
next(gen)

结果:

Traceback (most recent call last):
  File “learnException.py”, line 31, in
    next(gen)
StopIteration

StopAsyncIteration

必须由一个 asynchronous iterator 对象的 __anext__() 方法来引发以停止迭代操作。

没用过,有时间再说。

FloatingPointError

官网显示,Not currently used.不过,我记得在谋篇文章中提到numpy中有的,经过查找,找到了。

numpy的seterr源码

import numpy
numpy.seterr(invalid='raise')
numpy.sqrt(-1)

结果:

Traceback (most recent call last):
  File “learnException.py”, line 38, in
    numpy.sqrt(-1)
FloatingPointError: invalid value encountered in sqrt

OverflowError

算术运算的结果大到无法表示时将被引发。 这对整数来说不可能发生(宁可引发MemorryError也不会放弃尝试)。 但是出于历史原因,有时也会在整数超出要求范围的情况下引发 OverflowError。 因为在 C 中缺少对浮点异常处理的标准化,大多数浮点运算都不会做检查。

print(float('9' * (2 ** 99)))

结果:

Traceback (most recent call last):
  File “learnException.py”, line 37, in
    print(float(‘9’ * (2 ** 99)))
OverflowError: cannot fit ‘int’ into an index-sized integer

ZeroDivisionError

当除法或取余运算的第二个参数为零时将被引发。

print(2/0)

结果:

当除法或取余运算的第二个参数为零时将被引发。

AssertionError

assert语句失败时将被引发。讲到assert语句时再说。

AttributeError

属性引用或赋值失败时将被引发。

i = int(8)
i.abc = 9

结果:

Traceback (most recent call last):
  File “learnException.py”, line 43, in
    i.abc = 9
AttributeError: ‘int’ object has no attribute ‘abc’

BufferError

当与缓冲区相关的操作无法执行时将被引发。

没用过,有时间再说。

EOFError

input()函数未读取任何数据即达到文件结束条件 (EOF) 时将被引发。Linux上为Ctrl+d,Windows上为Ctrl+Z+Enter

s = input('please input something:')

博主的电脑是Windows,所以按的Ctrl+Z+Enter,结果:

please input something:^Z
Traceback (most recent call last):
  File “learnException.py”, line 45, in
    s = input(‘please input something:’)
EOFError

ModuleNotFoundError

当**import**语句尝试加载模块遇到麻烦时将被引发。 并且当 from ... impor...t 中的 “from list” 存在无法找到的名称时也会被引发。

import abcd

结果:

Traceback (most recent call last):
  File “learnException.py”, line 47, in
    import abcd
ModuleNotFoundError: No module named ‘abcd’

IndexError

序列索引超出范围时将被引发。

lst = [1, 2, 3]
print(lst[4])

结果:

Traceback (most recent call last):
  File “learnException.py”, line 50, in
    print(lst[4])
IndexError: list index out of range

KeyError

当在现有键集合中找不到指定的映射(字典)键时将被引发。

d = {“k”: “y”} print(d[“k”], d[1])

结果:

Traceback (most recent call last):
  File “learnException.py”, line 53, in
    print(d[“k”], d[1])
KeyError: 1

MemoryError

当一个操作耗尽内存但情况仍可进行挽救(通过删除一些对象)时将被引发。 关联的值是一个字符串,指明是哪种(内部)操作耗尽了内存。 请注意由于底层的内存管理架构(C 的 malloc() 函数),解释器也许并不总是能够从这种情况下完全恢复;但它毕竟可以引发一个异常,这样就能打印出栈回溯信息,以便找出导致问题的失控程序。

还没碰到过,有时间再说。听做大数据或爬虫之类的朋友说,读取一个大文件之类的可能会造成这个异常。

我从stackoverflow上找了一个例子。

大概的意思是变量u是一个很大的矩阵,提问题的人使用了u = u + alpha * p,内存会保留u,开辟空间存储u + alpha * p,将u指向u + alpha * p,然后释放原来u的内存空间,如果不考虑alpha和p的内存空间,执行该语句时内存空间至少分配了两个u的大小,解决问题的人使用了非简单赋值操作符p *= alpha,u += p,减少了内存空间的使用。关于操作符,可查看:Python-操作符总结(逻辑、位、算术、比较、赋值操作符及操作符优先级)

我们验证一下:

lst = [1]
id(lst)
1821366910152
lst = lst + [2]
id(lst)
1821366870280
lst += [2]
id(lst)
1821366870280

确实使用 += 时,id不会改变。

NameError

某个局部或全局名称未找到时将被引发。此异常仅用于非限定名称。 关联的值是一条错误信息,其中包含未找到的名称。

print(i)

结果:

Traceback (most recent call last):
  File “learnException.py”, line 55, in
    print(i)
NameError: name ‘i’ is not defined

UnboundLocalError

在函数或方法中对某个局部变量进行引用,但该变量并未绑定任何值时将被引发。 此异常是NameError的一个子类。

def Hi():
    hi += 1
    print(hi)


Hi()

结果:

Traceback (most recent call last):
  File “learnException.py”, line 63, in
    Hi()
  File “learnException.py”, line 59, in Hi
    hi += 1
UnboundLocalError: local variable ‘hi’ referenced before assignment

BlockingIOError

当一个操作会被某个设置为非阻塞操作的对象(例如套接字)所阻塞时将被引发。 对应于 errno EAGAIN, EALREADY, EWOULDBLOCKEINPROGRESS

除了OSError已有的属性,BlockingIOError还有一个额外属性:

characters_written

一个整数,表示在被阻塞前已写入到流的字符数。 当使用来自io模块的带缓冲 I/O 类时此属性可用。

还没有碰到过,继续stackoverflow。看了一页,总结一下:

  • 发送缓冲区已满却想继续发送到缓冲区
  • 接收缓冲区已空却想继续从缓冲区读取

也就是说你使用了非阻塞,那么就不会挂起去等待临界资源。

ChildProcessError

一个子进程上的操作失败时将被引发。 对应于 errno ECHILD

继续stackoverflow

他exec里面的命令写的有问题,也就是说python调用第三方的exe等如果出错可能会显示这个错误,遇到了再更新。

BrokenPipeError

当试图写入另一端已被关闭的管道,或是试图写入已关闭写入的套接字时将被引发。 对应于 errno EPIPEESHUTDOWN

stackoverflow找了一个,也不是很合适,这个错误貌似比较玄学…

我使用了他的代码,但是并没有出现他的异常,他虽然关闭了,但是之后没有使用in_1变量。我修改了一下代码,文件关闭再读取,但是得到的是 ValueError: I/O operation on closed file.

ConnectionAbortedError

连接尝试被对端中止时将被引发。 对应于 errno ECONNABORTED

例如,TCP类型的socket,socket.connect()被对方终止,就会出现这个异常。

ConnectionRefusedError

连接尝试被对端拒绝时将被引发。 对应于 errno ECONNREFUSED

import socket

IP = '127.0.0.1'
PORT = 80

# 建立Tcp一个客户端
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((IP, PORT))
hex_data = f"01000008"
DATA = bytes.fromhex(hex_data)
client.sendall(DATA)
client.close()

结果:

Traceback (most recent call last):
  File “learnException.py”, line 71, in
    client.connect((IP, PORT))
ConnectionRefusedError: [WinError 10061] 由于目标计算机积极拒绝,无法连接。

当然,你的80端口不能开着并接收信息。

ConnectionResetError

连接被对端重置时将被引发。 对应于 errno ECONNRESET

还没碰到过,有时间再说。

FileExistsError

当试图创建一个已存在的文件或目录时将被引发。 对应于 errno EEXIST

import os

os.mkdir('dist')

结果:

Traceback (most recent call last):
  File “learnException.py”, line 79, in
    os.mkdir(‘dist’)
FileExistsError: [WinError 183] 当文件已存在时,无法创建该文件。: ‘dist’

注意:dist目录在运行前已存在

FileNotFoundError

所请求的文件或目录不存在时将被引发。 对应于 errno ENOENT

with open('Nothing', 'r') as f:
    f.read()

结果:

Traceback (most recent call last):
  File “learnException.py”, line 81, in
    with open(‘Nothing’, ‘r’) as f:
FileNotFoundError: [Errno 2] No such file or directory: ‘Nothing’

注意:当前目录下并没有Nothing这个文件

InterruptedError

系统调用被输入信号中断时将被引发。 对应于 errno EINTR。

还没碰到过,有时间再说。

IsADirectoryError

请求对一个目录执行文件操作 (例如 os.remove()) 将被引发。 对应于 errno EISDIR

还没碰到过,有时间再说。

NotADirectoryError

当请求对一个非目录对象执行目录操作 (例如os.listdir()) 时将被引发。 对应于 errno ENOTDIR

import os
os.listdir('citys.csv')

结果:

Traceback (most recent call last):
  File “learnException.py”, line 88, in
    os.listdir(‘citys.csv’)
NotADirectoryError: [WinError 267] 目录名称无效。: ‘citys.csv’

PermissionError

在没有足够操作权限的情况下试图执行某个操作时将被引发 —— 例如缺少文件系统权限。 对应于 errno EACCESEPERM

使用Python-记一次U盘中病毒及文件找回中的脚本,对插入的U盘进行权限限制,之后拔插U盘。

import os

os.mkdir(r'G:\adirectory')

结果:

Traceback (most recent call last):
  File “learnException.py”, line 89, in
    os.mkdir(r’G:\adirectory’)
PermissionError: [WinError 5] 拒绝访问。: ‘G:\adirectory’

ProcessLookupError

给定的进程不存在时将被引发。 对应于 errno ESRCH

import os

os.kill(12345, 0)

结果:

Traceback (most recent call last):
  File “learnException.py”, line 89, in
    os.kill(12345, 0)
ProcessLookupError: [Errno 3] No such process

注意:博主在Linux测试是这样的,在Windows下是:

Traceback (most recent call last):
  File “learnException.py”, line 89, in
    os.kill(12345, 0)
OSError: [WinError 87] 参数错误。

TimeoutError

一个系统函数发生系统级超时的情况下将被引发。 对应于 errno ETIMEDOUT

还没碰到过,有时间再说。

ReferenceError

ReferenceError

此异常将在使用weakref.proxy()函数所创建的弱引用来访问该引用的某个已被作为垃圾回收的属性时被引发。

还没用过这个模块,有时间再说。

RuntimeError

RuntimeError

当检测到一个不归属于任何其他类别的错误时将被引发。

NotImplementedError

在用户自定义的基类中,抽象方法应当在其要求所派生类重载该方法,或是在其要求所开发的类提示具体实现尚待添加时引发此异常。

from abc import abstractmethod


class People:

    @abstractmethod
    def say(self):
        raise NotImplementedError('function say not implemented!')


class Man(People):
    pass


man = Man()
man.say()

结果:

Traceback (most recent call last):
  File “learnException.py”, line 109, in
    man.say()
  File “learnException.py”, line 101, in say
    raise NotImplementedError(‘function say not implemented!’)
NotImplementedError: function say not implemented!

经测试,只有抽象方法未实现,主动抛出异常,且该方法被调用时才会出现该异常。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以点击这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值