抛出异常
# {}.sort()
# assert True is False
# [][0]
# {}['']
# 1 / 0
# open("")
# _
# hello world
# print(list(range(10000000000))) # MemoryError
try:
x = 1 / 0
except ZeroDivisionError as original_exception:
print({}['error'])
# 重新抛出该异常
raise
try:
x = 1 / 0
except ZeroDivisionError as original_exception:
print({}['error'])
# 将original_exception抛出
raise original_exception
try:
x = 1 / 0
except ZeroDivisionError as original_exception:
# 引发一个新的异常,同时保留原始异常信息
raise ValueError("An error occurred") from original_exception
try:
x = 1 / 0
except ZeroDivisionError as original_exception:
print({}['error'])
raise ValueError("An error occurred") from original_exception
try-except[*]-else-finally
执行顺序与返回值
除i的类型不同外,其余逻辑均相同,比较i作为整型和i作为列表的两种情况下的返回值,i为整型时,后两次返回值不一样,i为列表时,后两次返回值异常。此处利用不可变类型和可变类型的特点可反映出try-except时返回值如何处理的,执行return先记录返回值地址,然后走完后续try-except流程,返回这个地址中的对象。
i为整型,初始值为1,分别返回1、2、3
def return_int(x):
try:
i = 1
if x == 1:
return i
except Exception as error:
print(error)
else:
i += 1
print("无异常执行else")
if x == 2:
return i
finally:
i += 1
print("不管代码是否有问题均执行finally")
if x == 3:
return i
# 正常 try -> else -> finally
# 异常 try -> except -> finally
# try返回值 x == 1
print("→", return_int(1))
# 不管代码是否有问题均执行finally
# → 1
# else返回值 x == 2
print("→", return_int(2))
# 无异常执行else
# 不管代码是否有问题均执行finally
# → 2
# finally返回值 x == 3
print("→", return_int(3))
# 无异常执行else
# 不管代码是否有问题均执行finally
# → 3
i为列表,初始值为[1],分别返回[1, 3]、[1, 2, 3]、[1, 2, 3]
def return_int(x):
try:
i = [1]
if x == 1:
return i
except Exception as error:
print(error)
else:
i.append(2)
print("无异常执行else")
if x == 2:
return i
finally:
i.append(3)
print("不管代码是否有问题均执行finally")
if x == 3:
return i
# 正常 try -> else -> finally
# 异常 try -> except -> finally
# try返回值 x == 1
print("→", return_int(1))
# 不管代码是否有问题均执行finally
# → [1, 3]
# else返回值 x == 2
print("→", return_int(2))
# 无异常执行else
# 不管代码是否有问题均执行finally
# → [1, 2, 3]
# finally返回值 x == 3
print("→", return_int(3))
# 无异常执行else
# 不管代码是否有问题均执行finally
# → [1, 2, 3]
单异常处理
except处理异常组也只处理一次,异常组本质上也是一种异常
import builtins # 手动导入也没问题
def division(a, b, c, d, f, g):
try:
type([1, 2, 3][a])
if b:
raise UserWarning('UserWarning')
c / d
if f:
eval("hia hia hia")
if g:
raise ExceptionGroup("group", [KeyError(), ValueError(), ExceptionGroup("sub_group", [OSError()])])
except IndexError:
print("IndexError")
except (Warning, ArithmeticError) as e:
print(e, type(e))
except ExceptionGroup as e:
print(e, type(e))
except Exception as e:
print('exception兜底', e, type(e)) # 应当在所有异常之后,用于异常捕获兜底
else:
print("无异常执行else")
finally:
print("不管代码是否有问题均执行finally")
print(division(0, False, 1, 1, False, builtins.str()))
# 无异常执行else
# 不管代码是否有问题均执行finally
# None
print(division(520, False, 1, 1, 0, builtins.str()))
# IndexError
# 不管代码是否有问题均执行finally
# None
print(division(0, True, 1, 1, 0, builtins.str()))
# UserWarning <class 'UserWarning'>
# 不管代码是否有问题均执行finally
# None
print(division(0, False, 1, 0, 0, builtins.str()))
# division by zero <class 'ZeroDivisionError'>
# 不管代码是否有问题均执行finally
# None
# 基于父类捕获异常 ArithmeticError是的父类ZeroDivisionError
print(division(0, False, 1, 1, 1, builtins.str()))
# exception兜底 invalid syntax (<string>, line 1) <class 'SyntaxError'>
# 不管代码是否有问题均执行finally
# None
# 通常使用Exception兜底,Exception为异常体系中大多数异常的父类
print(division(0, False, 1, 1, 0, builtins.str("-")))
# group (3 sub-exceptions) <class 'ExceptionGroup'>
# 不管代码是否有问题均执行finally
# 三个子异常
异常组处理
在Python3.11.4及以后引入异常组及except*语句,except*处理异常组会对异常组中每一个异常匹配一次
def division(a, b=1):
try:
match a / b:
case 1:
raise ZeroDivisionError()
case 2:
raise ExceptionGroup('error', [ValueError('value error'), TypeError('type error')])
case 3:
raise ExceptionGroup('error',
[ZeroDivisionError(), ExceptionGroup('param error', [ValueError('value error'),
TypeError('type error')])])
case 4:
raise ExceptionGroup('error', [ZeroDivisionError()])
case 5:
raise ZeroDivisionError
case 6:
raise ExceptionGroup('error', [ZeroDivisionError])
case 7:
raise ExceptionGroup('error',
[ZeroDivisionError, ExceptionGroup('param error', [ValueError('value error')])])
case 8:
raise ExceptionGroup('error', [ZeroDivisionError, KeyError(), ValueError])
except* ArithmeticError as e: # ZeroDivisionError的父类
print(1, e, type(e))
except* ValueError as e:
print(2, e, type(e))
except* KeyError as e:
print(3, e, type(e))
except* Exception as e:
print(4, e, type(e))
finally:
print("""↑↑↑""")
# except和except*不兼容
# SyntaxError: cannot have both 'except' and 'except*' on the same 'try'
division(1)
# 1 (1 sub-exception) <class 'ExceptionGroup'>
# 单个异常会被以异常组的方式捕获
division(2)
# 2 error (1 sub-exception) <class 'ExceptionGroup'>
# 4 error (1 sub-exception) <class 'ExceptionGroup'>
# 异常组中每个单个异常会被捕获一次
division(3)
# 1 error (1 sub-exception) <class 'ExceptionGroup'>
# 2 error (1 sub-exception) <class 'ExceptionGroup'>
# 4 error (1 sub-exception) <class 'ExceptionGroup'>
# 异常组可以嵌套为树状
division(4)
# 1 error (1 sub-exception) <class 'ExceptionGroup'>
division(5)
# 1 (1 sub-exception) <class 'ExceptionGroup'>
# ZeroDivisionError不带()可以被捕获
division(6)
# 2 (1 sub-exception) <class 'ExceptionGroup'>
# 但在异常组中不带()会报异常 ValueError: Item 0 of second argument (exceptions) is not an exception
# 没有匹配到 ArithmeticError
division(7)
# 2 (1 sub-exception) <class 'ExceptionGroup'>
# # 但在异常组中不带()会报异常
division(8)
# 2 (1 sub-exception) <class 'ExceptionGroup'>
# # 但在异常组中不带()会报异常
返回值机制
def division(x):
try:
i = 1
if x == 1:
return i
if x == 3:
raise ZeroDivisionError()
except Exception as error:
print(error)
i = 0
return i
else:
i = 2
print("无异常执行else")
return i
finally:
i = 3
print("不管代码是否有问题均执行finally")
if x == 4:
return i
# 正常执行
print("→", division(1))
# 不管代码是否有问题均执行finally
# → 1
print("→", division(2))
# 无异常执行else
# 不管代码是否有问题均执行finally
# → 2
# 重点看这个i的变化和输出值
print("→", division(3))
#
# 不管代码是否有问题均执行finally
# → 0
print("→", division(4))
# 无异常执行else
# 不管代码是否有问题均执行finally
# → 3
注:
try-except各个子块下变量在同一个命名空间
# 报错 i = 0 def func(): i += 2 print(i) func() # 不报错 try: i = 0 except Exception(): ... else: i += 1 finally: i += 1 print(i)
内置异常层次结构
exception-hierarchy,内置异常即builtins中的异常
BaseException 异常基类
├── BaseExceptionGroup 异常组基类
├── GeneratorExit 生成器退出
├── KeyboardInterrupt 键盘中断(通常是输入^C)
├── SystemExit 解释器退出
└── Exception 一般异常基类
├── ArithmeticError 计算错误基类
│ ├── FloatingPointError 浮点错误
│ ├── OverflowError 溢出错误,数值计算超出表示范围
│ └── ZeroDivisionError 除零错误
├── AssertionError 断言错误,断言语句断言失败
├── AttributeError 属性错误,访问对象没有的属性
├── BufferError 缓冲区错误
├── EOFError EOF错误
├── ExceptionGroup [BaseExceptionGroup]
├── ImportError 导入错误
│ └── ModuleNotFoundError 模块找不到错误
├── LookupError 查找错误,没访问到数据
│ ├── IndexError 索引错误,序列中没有该index
│ └── KeyError 键错误,字典中没有该key
├── MemoryError 内存错误,内存溢出
├── NameError 名称错误,标识符未声明
│ └── UnboundLocalError 未绑定的本地变量
├── OSError 操作系统错误
│ ├── BlockingIOError 阻塞IO错误
│ ├── ChildProcessError 子进程错误
│ ├── ConnectionError 连接错误
│ │ ├── BrokenPipeError
│ │ ├── ConnectionAbortedError 连接中止错误
│ │ ├── ConnectionRefusedError 连接拒绝错误
│ │ └── ConnectionResetError 连接重置错误
│ ├── FileExistsError 文件已存在错误
│ ├── FileNotFoundError 文件找不到错误
│ ├── InterruptedError 中断错误
│ ├── IsADirectoryError 是一个文件夹错误
│ ├── NotADirectoryError 不是一个文件夹错误
│ ├── PermissionError 权限错误
│ ├── ProcessLookupError 进程查找错误
│ └── TimeoutError 超时错误
├── ReferenceError 引用错误,弱引用访问已经被GC的对象
├── RuntimeError 运行时错误
│ ├── NotImplementedError 未实现错误,方法未实现
│ └── RecursionError 递归错误
├── StopAsyncIteration 停止异步迭代
├── StopIteration 停止迭代
├── SyntaxError 语法错误
│ └── IndentationError 缩进错误
│ └── TabError Tab错误,与space混用
├── SystemError 系统错误
├── TypeError 类型错误
├── ValueError 值错误
│ └── UnicodeError Unicode错误
│ ├── UnicodeDecodeError Unicode解码错误
│ ├── UnicodeEncodeError Unicode编码错误
│ └── UnicodeTranslateError Unicode转换错误
└── Warning 警告基类
├── BytesWarning bytes和bytearray相关警告的基类
├── DeprecationWarning 弃用警告
├── EncodingWarning 编码警告
├── FutureWarning 未来警告,未来版本中可能会发生变化
├── ImportWarning 导入警告
├── PendingDeprecationWarning 即将弃用警告
├── ResourceWarning 资源警告
├── RuntimeWarning 运行时警告
├── SyntaxWarning 语法警告
├── UnicodeWarning Unicode警告
└── UserWarning 用户警告
BaseException 为异常基类,通常情况下在自定义异常或希望捕获全部异常的情况下是使用一般异常基类Exception而非BaseException。在设计上,Exception作为一般异常基类,其同级异常都有专门用途,异常组基类BaseExceptionGroup用于构建异常组,生成器退出GeneratorExit用于在生成器退出时抛出,解释器本身捕获并处理该异常以使得生成器功能完整,键盘中断KeyboardInterrupt和解释器退出SystemExit都用于退出解释器,被捕获后若不二次抛出就无法退出解释器,与其原本目的不符。
关于生成器 GeneratorExit,发生在如下情况:
- 显式关闭:当调用生成器的
close()方法时。 - 迭代结束:当生成器的所有值都被迭代完毕后,迭代器的
__next__()方法会抛出StopIteration异常,这会触发生成器的close()方法,间接导致GeneratorExit被抛出。 - 异常传播:如果生成器在执行过程中遇到了异常,并且这个异常没有在生成器内部被捕获处理,那么异常会向上传播,最终可能触发生成器的
close()方法。
BaseException
class BaseException(object):
""" Common base class for all exceptions """
def add_note(self, note): # real signature unknown; restored from __doc__
"""
Exception.add_note(note) --
add a note to the exception
"""
pass
def with_traceback(self, tb): # real signature unknown; restored from __doc__
"""
Exception.with_traceback(tb) --
set self.__traceback__ to tb and return self.
"""
pass
def __delattr__(self, *args, **kwargs): # real signature unknown
""" Implement delattr(self, name). """
pass
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
def __reduce__(self, *args, **kwargs): # real signature unknown
pass
def __repr__(self, *args, **kwargs): # real signature unknown
""" Return repr(self). """
pass
def __setattr__(self, *args, **kwargs): # real signature unknown
""" Implement setattr(self, name, value). """
pass
def __setstate__(self, *args, **kwargs): # real signature unknown
pass
def __str__(self, *args, **kwargs): # real signature unknown
""" Return str(self). """
pass
args = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
__cause__ = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception cause"""
__context__ = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception context"""
__suppress_context__ = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
__traceback__ = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
__dict__ = None # (!) real value is "mappingproxy({'__new__': <built-in method __new__ of type object at 0x00007FF9479126B0>, '__repr__': <slot wrapper '__repr__' of 'BaseException' objects>, '__str__': <slot wrapper '__str__' of 'BaseException' objects>, '__getattribute__': <slot wrapper '__getattribute__' of 'BaseException' objects>, '__setattr__': <slot wrapper '__setattr__' of 'BaseException' objects>, '__delattr__': <slot wrapper '__delattr__' of 'BaseException' objects>, '__init__': <slot wrapper '__init__' of 'BaseException' objects>, '__reduce__': <method '__reduce__' of 'BaseException' objects>, '__setstate__': <method '__setstate__' of 'BaseException' objects>, 'with_traceback': <method 'with_traceback' of 'BaseException' objects>, 'add_note': <method 'add_note' of 'BaseException' objects>, '__suppress_context__': <member '__suppress_context__' of 'BaseException' objects>, '__dict__': <attribute '__dict__' of 'BaseException' objects>, 'args': <attribute 'args' of 'BaseException' objects>, '__traceback__': <attribute '__traceback__' of 'BaseException' objects>, '__context__': <attribute '__context__' of 'BaseException' objects>, '__cause__': <attribute '__cause__' of 'BaseException' objects>, '__doc__': 'Common base class for all exceptions'})"
class Exception(BaseException):
""" Common base class for all non-exit exceptions. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class BaseExceptionGroup(BaseException):
""" A combination of multiple unrelated exceptions. """
def derive(self, *args, **kwargs): # real signature unknown
pass
def split(self, *args, **kwargs): # real signature unknown
pass
def subgroup(self, *args, **kwargs): # real signature unknown
pass
def __class_getitem__(self, *args, **kwargs): # real signature unknown
""" See PEP 585 """
pass
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
def __str__(self, *args, **kwargs): # real signature unknown
""" Return str(self). """
pass
exceptions = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""nested exceptions"""
message = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception message"""
class GeneratorExit(BaseException):
""" Request that a generator exit. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class KeyboardInterrupt(BaseException):
""" Program interrupted by user. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class ExceptionGroup(BaseExceptionGroup, Exception):
# no doc
def __init__(self, *args, **kwargs): # real signature unknown
pass
__weakref__ = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""list of weak references to the object (if defined)"""
class ArithmeticError(Exception):
""" Base class for arithmetic errors. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class FloatingPointError(ArithmeticError):
""" Floating point operation failed. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class OverflowError(ArithmeticError):
""" Result too large to be represented. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class ZeroDivisionError(ArithmeticError):
""" Second argument to a division or modulo operation was zero. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class AssertionError(Exception):
""" Assertion failed. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class AttributeError(Exception):
""" Attribute not found. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
def __str__(self, *args, **kwargs): # real signature unknown
""" Return str(self). """
pass
name = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""attribute name"""
obj = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""object"""
class WindowsError(Exception):
""" Base class for I/O related errors. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
def __reduce__(self, *args, **kwargs): # real signature unknown
pass
def __str__(self, *args, **kwargs): # real signature unknown
""" Return str(self). """
pass
characters_written = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
errno = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""POSIX exception code"""
filename = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception filename"""
filename2 = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""second exception filename"""
strerror = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception strerror"""
winerror = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""Win32 exception code"""
OSError = WindowsError
IOError = WindowsError
EnvironmentError = WindowsError
class BlockingIOError(OSError):
""" I/O operation would block. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
class ConnectionError(OSError):
""" Connection error. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
class BrokenPipeError(ConnectionError):
""" Broken pipe. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
class ChildProcessError(OSError):
""" Child process error. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
class ConnectionAbortedError(ConnectionError):
""" Connection aborted. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
class ConnectionRefusedError(ConnectionError):
""" Connection refused. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
class ConnectionResetError(ConnectionError):
""" Connection reset. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
class FileExistsError(OSError):
""" File already exists. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
class FileNotFoundError(OSError):
""" File not found. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
class InterruptedError(OSError):
""" Interrupted by signal. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
class IsADirectoryError(OSError):
""" Operation doesn't work on directories. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
class NotADirectoryError(OSError):
""" Operation only works on directories. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
class PermissionError(OSError):
""" Not enough permissions. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
class ProcessLookupError(OSError):
""" Process not found. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
class TimeoutError(OSError):
""" Timeout expired. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
class BufferError(Exception):
""" Buffer error. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class Warning(Exception):
""" Base class for warning categories. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class BytesWarning(Warning):
"""
Base class for warnings about bytes and buffer related problems, mostly
related to conversion from str or comparing to str.
"""
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class DeprecationWarning(Warning):
""" Base class for warnings about deprecated features. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class EncodingWarning(Warning):
""" Base class for warnings about encodings. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class FutureWarning(Warning):
"""
Base class for warnings about constructs that will change semantically
in the future.
"""
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class ImportWarning(Warning):
""" Base class for warnings about probable mistakes in module imports """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class PendingDeprecationWarning(Warning):
"""
Base class for warnings about features which will be deprecated
in the future.
"""
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class ResourceWarning(Warning):
""" Base class for warnings about resource usage. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class RuntimeWarning(Warning):
""" Base class for warnings about dubious runtime behavior. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class SyntaxWarning(Warning):
""" Base class for warnings about dubious syntax. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class UnicodeWarning(Warning):
"""
Base class for warnings about Unicode related problems, mostly
related to conversion problems.
"""
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class UserWarning(Warning):
""" Base class for warnings generated by user code. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class EOFError(Exception):
""" Read beyond end of file. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class ImportError(Exception):
""" Import can't find module, or can't find name in module. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
def __reduce__(self, *args, **kwargs): # real signature unknown
pass
def __str__(self, *args, **kwargs): # real signature unknown
""" Return str(self). """
pass
msg = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception message"""
name = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""module name"""
path = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""module path"""
class ModuleNotFoundError(ImportError):
""" Module not found. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
class SyntaxError(Exception):
""" Invalid syntax. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
def __str__(self, *args, **kwargs): # real signature unknown
""" Return str(self). """
pass
end_lineno = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception end lineno"""
end_offset = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception end offset"""
filename = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception filename"""
lineno = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception lineno"""
msg = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception msg"""
offset = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception offset"""
print_file_and_line = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception print_file_and_line"""
text = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception text"""
class IndentationError(SyntaxError):
""" Improper indentation. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
class TabError(IndentationError):
""" Improper mixture of spaces and tabs. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
class LookupError(Exception):
""" Base class for lookup errors. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class IndexError(LookupError):
""" Sequence index out of range. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class KeyError(LookupError):
""" Mapping key not found. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
def __str__(self, *args, **kwargs): # real signature unknown
""" Return str(self). """
pass
class MemoryError(Exception):
""" Out of memory. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class NameError(Exception):
""" Name not found globally. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
def __str__(self, *args, **kwargs): # real signature unknown
""" Return str(self). """
pass
name = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""name"""
class UnboundLocalError(NameError):
""" Local name referenced but not bound to a value. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
class RuntimeError(Exception):
""" Unspecified run-time error. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class NotImplementedError(RuntimeError):
""" Method or function hasn't been implemented yet. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class RecursionError(RuntimeError):
""" Recursion limit exceeded. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class ReferenceError(Exception):
""" Weak ref proxy used after referent went away. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class StopAsyncIteration(Exception):
""" Signal the end from iterator.__anext__(). """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class StopIteration(Exception):
""" Signal the end from iterator.__next__(). """
def __init__(self, *args, **kwargs): # real signature unknown
pass
value = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""generator return value"""
class SystemError(Exception):
"""
Internal error in the Python interpreter.
Please report this to the Python maintainer, along with the traceback,
the Python version, and the hardware/OS platform and version.
"""
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class TypeError(Exception):
""" Inappropriate argument type. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class ValueError(Exception):
""" Inappropriate argument value (of correct type). """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class UnicodeError(ValueError):
""" Unicode related error. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
class UnicodeDecodeError(UnicodeError):
""" Unicode decoding error. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
def __str__(self, *args, **kwargs): # real signature unknown
""" Return str(self). """
pass
encoding = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception encoding"""
end = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception end"""
object = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception object"""
reason = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception reason"""
start = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception start"""
class UnicodeEncodeError(UnicodeError):
""" Unicode encoding error. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
def __str__(self, *args, **kwargs): # real signature unknown
""" Return str(self). """
pass
encoding = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception encoding"""
end = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception end"""
object = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception object"""
reason = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception reason"""
start = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception start"""
class UnicodeTranslateError(UnicodeError):
""" Unicode translation error. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
def __str__(self, *args, **kwargs): # real signature unknown
""" Return str(self). """
pass
encoding = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception encoding"""
end = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception end"""
object = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception object"""
reason = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception reason"""
start = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""exception start"""
异常栈
获取异常的traceback
print(Exception("xxx").__traceback__)
异常traceback
class MyException(Exception):
pass
def func6():
return 1 / 0
def func5():
func6()
def func4():
func5()
def func3():
try:
func4()
except Exception as exception:
...
raise exception
def func2():
func3()
def func1():
func2()
func1()
# Traceback (most recent call last):
# File "E:\python\pyBaseCode\demo.py", line 33, in <module>
# func1()
# File "E:\python\pyBaseCode\demo.py", line 30, in func1
# func2()
# File "E:\python\pyBaseCode\demo.py", line 26, in func2
# func3()
# File "E:\python\pyBaseCode\demo.py", line 22, in func3
# raise exception
# File "E:\python\pyBaseCode\demo.py", line 19, in func3
# func4()
# File "E:\python\pyBaseCode\demo.py", line 14, in func4
# func5()
# File "E:\python\pyBaseCode\demo.py", line 10, in func5
# func6()
# File "E:\python\pyBaseCode\demo.py", line 6, in func6
# return 1 / 0
# ~~^~~
# ZeroDivisionError: division by zero
https://docs.python.org/3/library/traceback.html
import sys
import traceback
try:
1 / 0
except Exception as e:
exc_type, exc_value, exc_traceback = sys.exc_info()
print(f"{exc_type=} {exc_value=} {exc_traceback=}")
traceback.print_exc()
# traceback封装了sys.exc_info()
traceback.print_tb(exc_traceback)
# traceback.print_tb(tb, limit=None, file=None)
# tb traceback object,可以由sys.exc_info获取到
# limit traceback层级限制,None为不限制返回所有层级
# file if file is None:
# file = sys.stderr
# for item in StackSummary.from_list(extracted_list).format():
# print(item, file=file, end="")
traceback.print_exception(exc_type, exc_value, exc_traceback, limit=None, file=sys.stdout)
# print_exception(exc, /, value=_sentinel, tb=_sentinel, limit=None, file=None, chain=True)
# 前三个参数正好是sys.exc_info()返回的三个值
traceback.format_exc()
上下文管理器处理异常
对上下文管理器本身出现问题不会处理,只处理包裹代码部分
class Context:
def __init__(self):
...
def __enter__(self):
1 / 0
...
def __exit__(self, exc_type, exc_val, exc_tb):
# 1 / 0
return True
with Context():
...
# Process finished with exit code 1
对返回值进行逻辑判断,真则表示无需将可能有的异常抛出,假则表示需要将可能有的异常抛出
class Context:
def __init__(self):
...
def __enter__(self):
...
def __exit__(self, exc_type, exc_val, exc_tb):
# Process finished with exit code 0
# 0 False [] ......
# "0" 1 True
return "0"
with Context():
1 / 0
ExitStack
嵌套多层上下文管理器
import abc
import os
import random
import sys
import _collections_abc
from collections import deque
from functools import wraps
from types import MethodType, GenericAlias
class AbstractContextManager(abc.ABC):
"""
上下文管理器的一个抽象基类
"""
__class_getitem__ = classmethod(GenericAlias)
def __enter__(self):
return self
@abc.abstractmethod
def __exit__(self, exc_type, exc_value, traceback):
return None
@classmethod
def __subclasshook__(cls, C):
if cls is AbstractContextManager:
return _collections_abc._check_methods(C, "__enter__", "__exit__")
return NotImplemented
class _BaseExitStack:
"""A base class for ExitStack and AsyncExitStack."""
@staticmethod
def _create_exit_wrapper(cm, cm_exit):
"""
使用 MethodType 函数来将 cm_exit 方法绑定到 cm 对象上
MethodType 是一个内置函数,它接收两个参数:一个方法和一个对象,然后返回一个绑定到该对象的方法。这意味着返回的方法在被调用时,self 参数将指向 cm 对象
cm_exit 是要绑定的cm的__exit__方法,其中 __exit__ 的参数为 self 和 各种异常信息
cm 是要绑定的对象,即上下文管理器对象本身
"""
return MethodType(cm_exit, cm)
@staticmethod
def _create_cb_wrapper(callback, /, *args, **kwds):
def _exit_wrapper(exc_type, exc, tb):
callback(*args, **kwds)
return _exit_wrapper
def __init__(self):
"""
deque 保存 经过包装后的 __exit__ 方法
"""
self._exit_callbacks = deque()
def pop_all(self):
"""Preserve the context stack by transferring it to a new instance."""
new_stack = type(self)()
new_stack._exit_callbacks = self._exit_callbacks
self._exit_callbacks = deque()
return new_stack
def push(self, exit):
"""
使用标准的__exit__方法签名注册回调。
可以像__exit__方法一样抑制异常。还接受具有__exit__方法的任何对象(注册对该方法的调用,而不是对象本身)。
"""
# We use an unbound method rather than a bound method to follow
# the standard lookup behaviour for special methods.
_cb_type = type(exit)
try:
exit_method = _cb_type.__exit__
except AttributeError:
# Not a context manager, so assume it's a callable.
self._push_exit_callback(exit)
else:
self._push_cm_exit(exit, exit_method)
return exit # Allow use as a decorator.
def enter_context(self, cm):
"""
1. 获取给定上下文管理器的 __enter__ 和 __exit__ 方法
2. 调用 __enter__ 并返回结果
3. 将 __exit__ 作为 callback 方法 push 入队列
"""
cls = type(cm)
try:
_enter = cls.__enter__
_exit = cls.__exit__
except AttributeError:
raise TypeError(f"'{cls.__module__}.{cls.__qualname__}' object does "
f"not support the context manager protocol") from None
result = _enter(cm)
self._push_cm_exit(cm, _exit)
return result
def callback(self, callback, /, *args, **kwds):
"""
注册支持任意参数的回调方法,不能像 __exit__ 方法一样压制异常
"""
_exit_wrapper = self._create_cb_wrapper(callback, *args, **kwds)
# We changed the signature, so using @wraps is not appropriate, but
# setting __wrapped__ may still help with introspection.
_exit_wrapper.__wrapped__ = callback
self._push_exit_callback(_exit_wrapper)
return callback # Allow use as a decorator
def _push_cm_exit(self, cm, cm_exit):
"""
1. 包装 __exit__ 方法
2. 入队列
"""
_exit_wrapper = self._create_exit_wrapper(cm, cm_exit)
self._push_exit_callback(_exit_wrapper, True)
def _push_exit_callback(self, callback, is_sync=True):
"""
包装后的方法入队列
"""
self._exit_callbacks.append((is_sync, callback))
# Inspired by discussions on http://bugs.python.org/issue13585
class ExitStack(_BaseExitStack, AbstractContextManager):
"""
用于动态管理退出回调堆栈的上下文管理器
"""
"""
For example:
with ExitStack() as stack:
files = [stack.enter_context(open(fname)) for fname in filenames]
# All opened files will automatically be closed at the end of
# the with statement, even if attempts to open files later
# in the list raise an exception.
"""
def __enter__(self):
return self
def __exit__(self, *exc_details):
received_exc = exc_details[0] is not None
# We manipulate the exception state so it behaves as though
# we were actually nesting multiple with statements
frame_exc = sys.exc_info()[1]
def _fix_exception_context(new_exc, old_exc):
# Context may not be correct, so find the end of the chain
while 1:
exc_context = new_exc.__context__
if exc_context is None or exc_context is old_exc:
# Context is already set correctly (see issue 20317)
return
if exc_context is frame_exc:
break
new_exc = exc_context
# Change the end of the chain to point to the exception
# we expect it to reference
new_exc.__context__ = old_exc
# 回调函数以先进后出顺序调用,模拟嵌套上下文管理器
suppressed_exc = False
pending_raise = False
while self._exit_callbacks:
# 弹出一个上下文管理器
is_sync, cb = self._exit_callbacks.pop()
assert is_sync
try:
# 执行回调,若该回调返回值为真,则压制异常不抛出
if cb(*exc_details):
suppressed_exc = True
pending_raise = False
exc_details = (None, None, None)
except:
# 执行回调时异常,pending_raise = True 准备抛出
new_exc_details = sys.exc_info()
# simulate the stack of exceptions by setting the context
_fix_exception_context(new_exc_details[1], exc_details[1])
pending_raise = True
exc_details = new_exc_details
if pending_raise:
try:
# bare "raise exc_details[1]" replaces our carefully
# set-up context
fixed_ctx = exc_details[1].__context__
raise exc_details[1]
except BaseException:
exc_details[1].__context__ = fixed_ctx
raise
return received_exc and suppressed_exc
def close(self):
"""Immediately unwind the context stack."""
self.__exit__(None, None, None)
if __name__ == '__main__':
with ExitStack() as exit_stack:
exit_stack.enter_context(open(str(random.Random().random()), "w+"))
raise Exception("123")
f = (open("123", "w+"), open("456", "w+"), open("789", "w+"))
with f:
...
from contextlib import ExitStack
with ExitStack() as stack:
for i in f:
stack.enter_context(i)
deprecated
import warnings
import functools
def deprecated(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
warnings.warn(f"{func.__name__} is deprecated. Use the new function instead.", DeprecationWarning, stacklevel=2)
return func(*args, **kwargs)
return wrapper
# 使用装饰器标记已弃用的函数
@deprecated
def old_function():
# 旧的功能实现
return "Old function"
def new_function():
# 新的功能实现
return "New function"
# 调用已弃用的函数
result_old = old_function()
# 调用新的函数
result_new = new_function()
print(result_old) # 输出警告信息并执行旧函数
print(result_new) # 执行新函数