# Python 自定义异常

> 原文： [https://www.programiz.com/python-programming/user-defined-exception](https://www.programiz.com/python-programming/user-defined-exception)

#### 在本教程中，您将借助示例学习如何根据需要定义自定义异常。

Python 有许多[内置异常](/python-programming/exceptions)，它们会在程序出现问题时强制您的程序输出错误。

但是，有时您可能需要创建自己的自定义异常来满足您的目的。

* * *

## 创建自定义异常

在 Python 中，用户可以通过创建新类来定义自定义异常。 必须从内置的`Exception`类直接或间接派生此异常类。 大多数内置异常也是从此类派生的。

```py
>>> class CustomError(Exception):
...     pass
...

>>> raise CustomError
Traceback (most recent call last):
...
__main__.CustomError

>>> raise CustomError("An error occurred")
Traceback (most recent call last):
...
__main__.CustomError: An error occurred
```

在这里，我们创建了一个名为`CustomError`的用户定义异常，该异常继承自`Exception`类。 与其他异常一样，可以使用`raise`语句以及可选的错误消息来引发此新异常。

当我们开发大型 Python 程序时，最好将程序引发的所有用户定义的异常放在单独的文件中。 许多标准模块可以做到这一点。 它们分别将其异常定义为`exceptions.py`或`errors.py`（通常但并非总是如此）。

用户定义的异常类可以实现普通类可以做的所有事情，但是我们通常使它们简单明了。 大多数实现都声明一个自定义基类，并从该基类派生其他异常类。 在下面的示例中，将使该概念更清晰。

* * *

## 示例：Python 中的用户定义异常

在此示例中，我们将说明如何在程序中使用用户定义的异常来引发和捕获错误。

该程序将要求用户输入一个数字，直到他们正确猜出一个存储的数字为止。 为了帮助他们弄清楚，他们的猜测是大于还是小于所存储的数字。

```py
# define Python user-defined exceptions
class Error(Exception):
    """Base class for other exceptions"""
    pass

class ValueTooSmallError(Error):
    """Raised when the input value is too small"""
    pass

class ValueTooLargeError(Error):
    """Raised when the input value is too large"""
    pass

# you need to guess this number
number = 10

# user guesses a number until he/she gets it right
while True:
    try:
        i_num = int(input("Enter a number: "))
        if i_num < number:
            raise ValueTooSmallError
        elif i_num > number:
            raise ValueTooLargeError
        break
    except ValueTooSmallError:
        print("This value is too small, try again!")
        print()
    except ValueTooLargeError:
        print("This value is too large, try again!")
        print()

print("Congratulations! You guessed it correctly.")
```

这是该程序的示例运行。

```py
Enter a number: 12
This value is too large, try again!

Enter a number: 0
This value is too small, try again!

Enter a number: 8
This value is too small, try again!

Enter a number: 10
Congratulations! You guessed it correctly.
```

我们定义了一个名为`Error`的基类。

我们程序实际引发的另外两个异常（`ValueTooSmallError`和`ValueTooLargeError`）是从此类派生的。 这是在 Python 编程中定义用户定义的异常的标准方法，但不仅限于此。

* * *

## 自定义异常类

我们可以进一步自定义此类，以根据需要接受其他参数。

要了解有关自定义`Exception`类的信息，您需要具有面向对象编程的基础知识。

访问 [Python 面向对象编程](/python-programming/object-oriented-programming)，开始学习 Python 中的面向对象编程。

让我们看一个例子：

```py
class SalaryNotInRangeError(Exception):
    """Exception raised for errors in the input salary.

    Attributes:
        salary -- input salary which caused the error
        message -- explanation of the error
    """

    def __init__(self, salary, message="Salary is not in (5000, 15000) range"):
        self.salary = salary
        self.message = message
        super().__init__(self.message)

salary = int(input("Enter salary amount: "))
if not 5000 < salary < 15000:
    raise SalaryNotInRangeError(salary)
```

**输出**

```py
Enter salary amount: 2000
Traceback (most recent call last):
  File "<string>", line 17, in <module>
    raise SalaryNotInRangeError(salary)
__main__.SalaryNotInRangeError: Salary is not in (5000, 15000) range
```

在这里，我们覆盖了`Exception`类的构造器，以接受我们自己的自定义参数`salary`和`message`。 然后，使用`super()`和`self.message`参数手动调用父`Exception`类的构造器。

自定义`self.salary`属性定义为以后使用。

然后，当引发`SalaryNotInRangeError`时，将使用`Exception`类的继承的`__str__`方法显示相应的消息。

我们也可以通过覆盖`__str__`方法本身来定制它。

```py
class SalaryNotInRangeError(Exception):
    """Exception raised for errors in the input salary.

    Attributes:
        salary -- input salary which caused the error
        message -- explanation of the error
    """

    def __init__(self, salary, message="Salary is not in (5000, 15000) range"):
        self.salary = salary
        self.message = message
        super().__init__(self.message)

    def __str__(self):
        return f'{self.salary} -> {self.message}'

salary = int(input("Enter salary amount: "))
if not 5000 < salary < 15000:
    raise SalaryNotInRangeError(salary)
```

**输出**：

```py
Enter salary amount: 2000
Traceback (most recent call last):
  File "/home/bsoyuj/Desktop/Untitled-1.py", line 20, in <module>
    raise SalaryNotInRangeError(salary)
__main__.SalaryNotInRangeError: 2000 -> Salary is not in (5000, 15000) range
```

* * *

要了解有关如何使用 Python 处理异常的更多信息，请访问 [Python 异常处理](/python-programming/exception-handling)。