在本教程中,您将借助示例学习如何根据需要定义自定义异常。
Python 有许多内置异常,它们会在程序出现问题时强制您的程序输出错误。
但是,有时您可能需要创建自己的自定义异常来满足您的目的。
创建自定义异常
在 Python 中,用户可以通过创建新类来定义自定义异常。 必须从内置的Exception
类直接或间接派生此异常类。 大多数内置异常也是从此类派生的。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<span class="pl-c1">>></span><span class="pl-c1">></span> <span class="pl-k">class</span> <span class="pl-v">CustomError</span>(<span class="pl-v">Exception</span>): ... <span class="pl-s1">pass</span> ... <span class="pl-c1">>></span><span class="pl-c1">></span> <span class="pl-k">raise</span> <span class="pl-v">CustomError</span> <span class="pl-v">Traceback</span> (<span class="pl-s1">most</span> <span class="pl-s1">recent</span> <span class="pl-s1">call</span> <span class="pl-s1">last</span>): ... <span class="pl-s1">__main__</span>.<span class="pl-v">CustomError</span> <span class="pl-c1">>></span><span class="pl-c1">></span> <span class="pl-k">raise</span> <span class="pl-v">CustomError</span>(<span class="pl-s">"An error occurred"</span>) <span class="pl-v">Traceback</span> (<span class="pl-s1">most</span> <span class="pl-s1">recent</span> <span class="pl-s1">call</span> <span class="pl-s1">last</span>): ... <span class="pl-s1">__main__</span>.<span class="pl-v">CustomError</span>: <span class="pl-v">An</span> <span class="pl-s1">error</span> <span class="pl-s1">occurred</span> |
在这里,我们创建了一个名为CustomError
的用户定义异常,该异常继承自Exception
类。 与其他异常一样,可以使用raise
语句以及可选的错误消息来引发此新异常。
当我们开发大型 Python 程序时,最好将程序引发的所有用户定义的异常放在单独的文件中。 许多标准模块可以做到这一点。 它们分别将其异常定义为exceptions.py
或errors.py
(通常但并非总是如此)。
用户定义的异常类可以实现普通类可以做的所有事情,但是我们通常使它们简单明了。 大多数实现都声明一个自定义基类,并从该基类派生其他异常类。 在下面的示例中,将使该概念更清晰。
示例:Python 中的用户定义异常
在此示例中,我们将说明如何在程序中使用用户定义的异常来引发和捕获错误。
该程序将要求用户输入一个数字,直到他们正确猜出一个存储的数字为止。 为了帮助他们弄清楚,他们的猜测是大于还是小于所存储的数字。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<span class="pl-c"># define Python user-defined exceptions</span> <span class="pl-k">class</span> <span class="pl-v">Error</span>(<span class="pl-v">Exception</span>): <span class="pl-s">"""Base class for other exceptions"""</span> <span class="pl-k">pass</span> <span class="pl-k">class</span> <span class="pl-v">ValueTooSmallError</span>(<span class="pl-v">Error</span>): <span class="pl-s">"""Raised when the input value is too small"""</span> <span class="pl-k">pass</span> <span class="pl-k">class</span> <span class="pl-v">ValueTooLargeError</span>(<span class="pl-v">Error</span>): <span class="pl-s">"""Raised when the input value is too large"""</span> <span class="pl-k">pass</span> <span class="pl-c"># you need to guess this number</span> <span class="pl-s1">number</span> <span class="pl-c1">=</span> <span class="pl-c1">10</span> <span class="pl-c"># user guesses a number until he/she gets it right</span> <span class="pl-k">while</span> <span class="pl-c1">True</span>: <span class="pl-k">try</span>: <span class="pl-s1">i_num</span> <span class="pl-c1">=</span> <span class="pl-en">int</span>(<span class="pl-en">input</span>(<span class="pl-s">"Enter a number: "</span>)) <span class="pl-k">if</span> <span class="pl-s1">i_num</span> <span class="pl-c1"><</span> <span class="pl-s1">number</span>: <span class="pl-k">raise</span> <span class="pl-v">ValueTooSmallError</span> <span class="pl-k">elif</span> <span class="pl-s1">i_num</span> <span class="pl-c1">></span> <span class="pl-s1">number</span>: <span class="pl-k">raise</span> <span class="pl-v">ValueTooLargeError</span> <span class="pl-k">break</span> <span class="pl-k">except</span> <span class="pl-v">ValueTooSmallError</span>: <span class="pl-en">print</span>(<span class="pl-s">"This value is too small, try again!"</span>) <span class="pl-en">print</span>() <span class="pl-k">except</span> <span class="pl-v">ValueTooLargeError</span>: <span class="pl-en">print</span>(<span class="pl-s">"This value is too large, try again!"</span>) <span class="pl-en">print</span>() <span class="pl-en">print</span>(<span class="pl-s">"Congratulations! You guessed it correctly."</span>) |
这是该程序的示例运行。
1 2 3 4 5 6 7 8 9 10 11 |
<span class="pl-v">Enter</span> <span class="pl-s1">a</span> <span class="pl-s1">number</span>: <span class="pl-c1">12</span> <span class="pl-v">This</span> <span class="pl-s1">value</span> <span class="pl-c1">is</span> <span class="pl-s1">too</span> <span class="pl-s1">large</span>, <span class="pl-s1">try</span> <span class="pl-s1">again</span>! <span class="pl-v">Enter</span> <span class="pl-s1">a</span> <span class="pl-s1">number</span>: <span class="pl-c1">0</span> <span class="pl-v">This</span> <span class="pl-s1">value</span> <span class="pl-c1">is</span> <span class="pl-s1">too</span> <span class="pl-s1">small</span>, <span class="pl-s1">try</span> <span class="pl-s1">again</span>! <span class="pl-v">Enter</span> <span class="pl-s1">a</span> <span class="pl-s1">number</span>: <span class="pl-c1">8</span> <span class="pl-v">This</span> <span class="pl-s1">value</span> <span class="pl-c1">is</span> <span class="pl-s1">too</span> <span class="pl-s1">small</span>, <span class="pl-s1">try</span> <span class="pl-s1">again</span>! <span class="pl-v">Enter</span> <span class="pl-s1">a</span> <span class="pl-s1">number</span>: <span class="pl-c1">10</span> <span class="pl-v">Congratulations</span>! <span class="pl-v">You</span> <span class="pl-s1">guessed</span> <span class="pl-s1">it</span> <span class="pl-s1">correctly</span>. |
我们定义了一个名为Error
的基类。
我们程序实际引发的另外两个异常(ValueTooSmallError
和ValueTooLargeError
)是从此类派生的。 这是在 Python 编程中定义用户定义的异常的标准方法,但不仅限于此。
自定义异常类
我们可以进一步自定义此类,以根据需要接受其他参数。
要了解有关自定义Exception
类的信息,您需要具有面向对象编程的基础知识。
访问 Python 面向对象编程,开始学习 Python 中的面向对象编程。
让我们看一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<span class="pl-k">class</span> <span class="pl-v">SalaryNotInRangeError</span>(<span class="pl-v">Exception</span>): <span class="pl-s">"""Exception raised for errors in the input salary.</span> <span class="pl-s"></span> <span class="pl-s"> Attributes:</span> <span class="pl-s"> salary -- input salary which caused the error</span> <span class="pl-s"> message -- explanation of the error</span> <span class="pl-s"> """</span> <span class="pl-k">def</span> <span class="pl-en">__init__</span>(<span class="pl-s1">self</span>, <span class="pl-s1">salary</span>, <span class="pl-s1">message</span><span class="pl-c1">=</span><span class="pl-s">"Salary is not in (5000, 15000) range"</span>): <span class="pl-s1">self</span>.<span class="pl-s1">salary</span> <span class="pl-c1">=</span> <span class="pl-s1">salary</span> <span class="pl-s1">self</span>.<span class="pl-s1">message</span> <span class="pl-c1">=</span> <span class="pl-s1">message</span> <span class="pl-en">super</span>().<span class="pl-en">__init__</span>(<span class="pl-s1">self</span>.<span class="pl-s1">message</span>) <span class="pl-s1">salary</span> <span class="pl-c1">=</span> <span class="pl-en">int</span>(<span class="pl-en">input</span>(<span class="pl-s">"Enter salary amount: "</span>)) <span class="pl-k">if</span> <span class="pl-c1">not</span> <span class="pl-c1">5000</span> <span class="pl-c1"><</span> <span class="pl-s1">salary</span> <span class="pl-c1"><</span> <span class="pl-c1">15000</span>: <span class="pl-k">raise</span> <span class="pl-v">SalaryNotInRangeError</span>(<span class="pl-s1">salary</span>) |
输出
1 2 3 4 5 |
<span class="pl-v">Enter</span> <span class="pl-s1">salary</span> <span class="pl-s1">amount</span>: <span class="pl-c1">2000</span> <span class="pl-v">Traceback</span> (<span class="pl-s1">most</span> <span class="pl-s1">recent</span> <span class="pl-s1">call</span> <span class="pl-s1">last</span>): <span class="pl-v">File</span> <span class="pl-s">"<string>"</span>, <span class="pl-s1">line</span> <span class="pl-c1">17</span>, <span class="pl-s1">in</span> <span class="pl-c1"><</span><span class="pl-s1">module</span><span class="pl-c1">></span> <span class="pl-s1">raise</span> <span class="pl-v">SalaryNotInRangeError</span>(<span class="pl-s1">salary</span>) <span class="pl-s1">__main__</span>.<span class="pl-v">SalaryNotInRangeError</span>: <span class="pl-v">Salary</span> <span class="pl-c1">is</span> <span class="pl-c1">not</span> <span class="pl-en">in</span> (<span class="pl-c1">5000</span>, <span class="pl-c1">15000</span>) <span class="pl-s1">range</span> |
在这里,我们覆盖了Exception
类的构造器,以接受我们自己的自定义参数salary
和message
。 然后,使用super()
和self.message
参数手动调用父Exception
类的构造器。
自定义self.salary
属性定义为以后使用。
然后,当引发SalaryNotInRangeError
时,将使用Exception
类的继承的__str__
方法显示相应的消息。
我们也可以通过覆盖__str__
方法本身来定制它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<span class="pl-k">class</span> <span class="pl-v">SalaryNotInRangeError</span>(<span class="pl-v">Exception</span>): <span class="pl-s">"""Exception raised for errors in the input salary.</span> <span class="pl-s"></span> <span class="pl-s"> Attributes:</span> <span class="pl-s"> salary -- input salary which caused the error</span> <span class="pl-s"> message -- explanation of the error</span> <span class="pl-s"> """</span> <span class="pl-k">def</span> <span class="pl-en">__init__</span>(<span class="pl-s1">self</span>, <span class="pl-s1">salary</span>, <span class="pl-s1">message</span><span class="pl-c1">=</span><span class="pl-s">"Salary is not in (5000, 15000) range"</span>): <span class="pl-s1">self</span>.<span class="pl-s1">salary</span> <span class="pl-c1">=</span> <span class="pl-s1">salary</span> <span class="pl-s1">self</span>.<span class="pl-s1">message</span> <span class="pl-c1">=</span> <span class="pl-s1">message</span> <span class="pl-en">super</span>().<span class="pl-en">__init__</span>(<span class="pl-s1">self</span>.<span class="pl-s1">message</span>) <span class="pl-k">def</span> <span class="pl-en">__str__</span>(<span class="pl-s1">self</span>): <span class="pl-k">return</span> <span class="pl-s">f'<span class="pl-s1"><span class="pl-kos">{</span><span class="pl-s1">self</span>.<span class="pl-s1">salary</span><span class="pl-kos">}</span></span> -> <span class="pl-s1"><span class="pl-kos">{</span><span class="pl-s1">self</span>.<span class="pl-s1">message</span><span class="pl-kos">}</span></span>'</span> <span class="pl-s1">salary</span> <span class="pl-c1">=</span> <span class="pl-en">int</span>(<span class="pl-en">input</span>(<span class="pl-s">"Enter salary amount: "</span>)) <span class="pl-k">if</span> <span class="pl-c1">not</span> <span class="pl-c1">5000</span> <span class="pl-c1"><</span> <span class="pl-s1">salary</span> <span class="pl-c1"><</span> <span class="pl-c1">15000</span>: <span class="pl-k">raise</span> <span class="pl-v">SalaryNotInRangeError</span>(<span class="pl-s1">salary</span>) |
输出:
1 2 3 4 5 |
<span class="pl-v">Enter</span> <span class="pl-s1">salary</span> <span class="pl-s1">amount</span>: <span class="pl-c1">2000</span> <span class="pl-v">Traceback</span> (<span class="pl-s1">most</span> <span class="pl-s1">recent</span> <span class="pl-s1">call</span> <span class="pl-s1">last</span>): <span class="pl-v">File</span> <span class="pl-s">"/home/bsoyuj/Desktop/Untitled-1.py"</span>, <span class="pl-s1">line</span> <span class="pl-c1">20</span>, <span class="pl-s1">in</span> <span class="pl-c1"><</span><span class="pl-s1">module</span><span class="pl-c1">></span> <span class="pl-s1">raise</span> <span class="pl-v">SalaryNotInRangeError</span>(<span class="pl-s1">salary</span>) <span class="pl-s1">__main__</span>.<span class="pl-v">SalaryNotInRangeError</span>: <span class="pl-c1">2000</span> <span class="pl-c1">-</span><span class="pl-c1">></span> <span class="pl-v">Salary</span> <span class="pl-c1">is</span> <span class="pl-c1">not</span> <span class="pl-en">in</span> (<span class="pl-c1">5000</span>, <span class="pl-c1">15000</span>) <span class="pl-s1">range</span> |
要了解有关如何使用 Python 处理异常的更多信息,请访问 Python 异常处理。