在Python中的错误可(至少)被分为两种:语法错误
和 异常
,均是指在程序中发生的问题和意外情况。Python提供了异常处理机制,使程序能够更容易地应对这些问题。
语法错误
,又称解析错误,是Python中常见的错误,主要是因为代码不符合Python语法规则而引起的错误,它们在代码解析阶段就会被检测,因此程序无法继续执行。解析器会复现出现句法错误的代码行,并用小“箭头”指向行里检测到的第一个错误。
下面是一些语法错误的示例:
1)缺少冒号
while True print('hello world')
``![在这里插入图片描述](https://img-blog.csdnimg.cn/baf0b6e94ae04a0b9fc40891e8de5fcb.png#pic_center)
  **2)括号不匹配**
```python
print('hello world!'
3)缩进错误
if True:
print('Indented incorrectly')
4)关键字拼写错误
whil True:
print('Misspelled keyword')
即使语句或表达式使用了正确的语法,执行时仍可能触发错误。执行时检测到的错误称为 异常
,异常不一定导致严重的后果。大多数异常是由于程序错误、外部调减变化或其他意外情况引起的,不会被程序处理,而是显示错误信息,下面示例说明:
1)零除错误(ZeroDivisionError)
# ZeroDivisionError 的示例
result = 10 / 0
2)NameError
# NameError 的示例
print(undefined_variable)
3)类型错误(TypeError)
# TypeError 的示例
result = "5" + 3
4) 运行时异常
# 未明确指定异常引发 RuntimeError
def example_function():
raise RuntimeError("An unspecified runtime error occurred.")
example_function()
内置异常结构:
BaseException
├── BaseExceptionGroup
├── GeneratorExit
├── KeyboardInterrupt
├── SystemExit
└── Exception
├── ArithmeticError
│ ├── FloatingPointError
│ ├── OverflowError
│ └── ZeroDivisionError
├── AssertionError
├── AttributeError
├── BufferError
├── EOFError
├── ExceptionGroup [BaseExceptionGroup]
├── 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
├── StopAsyncIteration
├── StopIteration
├── SyntaxError
│ └── IndentationError
│ └── TabError
├── SystemError
├── TypeError
├── ValueError
│ └── UnicodeError
│ ├── UnicodeDecodeError
│ ├── UnicodeEncodeError
│ └── UnicodeTranslateError
└── Warning
├── BytesWarning
├── DeprecationWarning
├── EncodingWarning
├── FutureWarning
├── ImportWarning
├── PendingDeprecationWarning
├── ResourceWarning
├── RuntimeWarning
├── SyntaxWarning
├── UnicodeWarning
└── UserWarning
异常处理是一种在程序执行过程中检测、响应和处理异常的机制。在 Python 中,异常处理通常使用 try
、except
、else
和 finally
关键字。
try
语句的工作原理如下:
1)首先,执行 try 子句
(try
和 except
关键字之间的(多行)语句)。
2)如果没有触发异常,则跳过except
子句,try
语句执行完毕。
3)如果在执行 try
子句时发生了异常,则跳过该子句中剩下的部分。 如果异常的类型与 except
关键字后指定的异常相匹配,则会执行 except
子句,然后跳到 try/except
代码块之后继续执行。
4)如果发生的异常与except
子句 中指定的异常不匹配,则它会被传递到外部的 try
语句中;如果没有找到处理程序,则它是一个 未处理异常 且执行将终止并输出如上所示的消息。
try
语句可以有多个 except
子句 来为不同的异常指定处理程序。 但最多只有一个处理程序会被执行。 处理程序只处理对应的 try
子句 中发生的异常,而不处理同一try
语句内其他处理程序中的异常。 except
子句 可以用带圆括号的元组来指定多个异常。
下面是异常处理的基本结构:
try:
# 尝试执行可能引发异常的代码
num = int(input("Enter a number: "))
result = 10 / num
except ZeroDivisionError:
# 处理除以零的异常
print("Cannot divide by zero.")
except ValueError as ve:
# 处理输入非整数的异常
print(f"Invalid input: {ve}")
else:
# 如果没有异常发生时执行的代码
print(f"Result: {result}")
finally:
# 无论是否发生异常都执行的代码
print("Execution complete.")
try
块包含可能引发异常的代码。
如果在try
块中发生异常,程序将跳转到匹配的 except
块来处理异常。
except
块可以捕获特定类型的异常,并提供相应的处理代码。
else
块包含在没有异常发生时执行的代码。
finally
块包含无论是否发生异常都会执行的代码,通常用于清理工作。
可以使用raise
语句来主动触发异常。raise
语句允许你在程序执行过程中引发特定类型的异常,以便在需要的时候中断程序的正常流程并执行相应的异常处理代码。
def divide_numbers(a, b):
if b == 0:
raise ValueError("Cannot divide by zero.")
else:
return a / b
try:
result = divide_numbers(10, 2)
print(f"Result: {result}")
# 触发异常
result = divide_numbers(5, 0)
print(f"Result: {result}") # 这一行不会被执行
except ValueError as ve:
print(f"Caught a ValueError: {ve}")
finally:
print("Execution complete.")
在这个例子中,divide_numbers
函数尝试执行除法操作。如果除数 b
是零,就会触发 ValueError
异常,指示不能除以零。在 try 块中,先调用了 divide_numbers(10, 2),然后再调用了 divide_numbers(5, 0)。由于除以零,导致了ValueError
异常的触发。
在有些情况下,有必要报告几个已经发生的异常。这通常是在并发框架中当几个任务并行失败时的情况,但也有其他的用例,有时需要是继续执行并收集多个错误而不是引发第一个异常。
内置的 ExceptionGroup
打包了一个异常实例的列表,这样它们就可以一起被引发。它本身就是一个异常,所以它可以像其他异常一样被捕获。
def f():
excs = [OSError('error 1'), SystemError('error 2')]
raise ExceptionGroup('there were problems', excs)
f()
引发异常信息:
捕获异常:
# 捕获异常 输出 caught : e
try:
f()
except Exception as e:
print(f'caught {type(e)}: e')
当一个异常被创建以引发时,它通常被初始化为描述所发生错误的信息。在有些情况下,在异常被捕获后添加信息是很有用的。为了这个目的,异常有一个 add_note(note)
方法接受一个字符串,并将其添加到异常的注释列表。标准的回溯在异常之后按照它们被添加的顺序呈现包括所有的注释。
try:
raise TypeError('bad type')
except Exception as e:
e.add_note('Add some information')
e.add_note('Add some more information')
raise
例如,当把异常收集到一个异常组时,可能想为各个错误添加上下文信息。在下文中,组中的每个异常都有一个说明,指出这个错误是什么时候发生的。
def f():
raise OSError('operation failed')
excs = []
for i in range(3):
try:
f()
except Exception as e:
e.add_note(f'Happened in Iteration {i+1}')
excs.append(e)
raise ExceptionGroup('We have some problems', excs)