{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Exceptions\n", "\"Open\n", "\n", "\n", "http://openbookproject.net/thinkcs/python/english3e/exceptions.html\n", "- dealing with bugs is normal part of programming\n", "- debugging is a very handy programming skill\n", "\n", "## category of bugs\n", "- syntax errors\n", "- logical/semantic errros\n", "- runtime errors/exceptions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## exceptions\n", "- when runtime error occurs, it creats an exception object\n", "- program halts; Python prints out the traceback with error message\n", "- https://docs.python.org/3/tutorial/errors.html" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "ename": "ZeroDivisionError", "evalue": "division by zero", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m55\u001b[0m\u001b[0;34m/\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mZeroDivisionError\u001b[0m: division by zero" ] } ], "source": [ "print(55/0)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "ename": "IndexError", "evalue": "list index out of range", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0malist\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0malist\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mIndexError\u001b[0m: list index out of range" ] } ], "source": [ "alist = []\n", "print(alist[0])" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "'tuple' object does not support item assignment", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0matup\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m'a'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'b'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'c'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0matup\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'A'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mTypeError\u001b[0m: 'tuple' object does not support item assignment" ] } ], "source": [ "atup = ('a', 'b', 'c')\n", "atup[0] = 'A'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- each exception has two parts- Name: description" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## catching exceptions\n", "- use try and except blocks\n", "- try statement has several separate clauses/parts\n", "
\n",
    "    try:\n",
    "        # statement(s) thay may potentially throw(s) exception\n",
    "    except ExceptionName1:\n",
    "        # catch specific exception ExceptionName1\n",
    "        # statement(s) to handle the exception\n",
    "    [except ExceptionName2 as err:\n",
    "        # statements\n",
    "    ]\n",
    "    [except:\n",
    "        # catch any error not caught by previous except blocks\n",
    "    ]\n",
    "    [else:\n",
    "        # follows all except clause\n",
    "        # executes if try clause does NOT raise an exception\n",
    "    ]\n",
    "    [finally:\n",
    "        # clean-up actions that must be executed under all circumstances; \n",
    "        # exectued on the way out when try block is left via a break, continue, or return statement\n",
    "    ]\n",
    "
\n", "- [ ] optional " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### example 1" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Enter dividend: 10\n", "Enter divisor: 2\n", "quotient= 5.0\n", "remainder= 0\n", "executing finally clause\n" ] } ], "source": [ "try:\n", " x = int(input(\"Enter dividend: \"))\n", " y = int(input(\"Enter divisor: \"))\n", " quotient = x/y\n", " remainder = x%y\n", "except ZeroDivisionError as ex:\n", " print('Exception occured:', ex)\n", " print('arguments:', ex.args)\n", "except:\n", " print('Some exception occured...')\n", "else:\n", " print(\"quotient=\", quotient)\n", " print(\"remainder=\", remainder)\n", "finally:\n", " print(\"executing finally clause\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### example 2\n", "- input validation" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Please enter a number: f\n", "Oops! That was not a valid number. Try again...\n", "Please enter a number: dsaf\n", "Oops! That was not a valid number. Try again...\n", "Please enter a number: adsf\n", "Oops! That was not a valid number. Try again...\n", "Please enter a number: asdf\n", "Oops! That was not a valid number. Try again...\n", "Please enter a number: 10\n" ] } ], "source": [ "while True:\n", " try:\n", " x = int(input(\"Please enter a number: \"))\n", " break\n", " except ValueError:\n", " print(\"Oops! That was not a valid number. Try again...\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## raising exceptions\n", " - raise statement allows programer to throw their own exceptions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### example 1" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "ename": "NameError", "evalue": "MyException", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mNameError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"MyException\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mNameError\u001b[0m: MyException" ] } ], "source": [ "raise NameError(\"MyException\")" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "An exception flew by...\n" ] }, { "ename": "NameError", "evalue": "My Exception", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mNameError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'My Exception'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mNameError\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'An exception flew by...'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32mraise\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mNameError\u001b[0m: My Exception" ] } ], "source": [ "try:\n", " raise NameError('My Exception')\n", "except NameError:\n", " print('An exception flew by...')\n", " raise" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## user-defined exceptions\n", "- one can define their own exceptions and raise them as needed\n", "- should typically derive from the Exception class, either directly or indirectly\n", "\n", "### example 1" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class InputError(Exception):\n", " \"\"\"\n", " Exception raised for errors in the input.\n", " \n", " Attributes:\n", " expression -- input expression in which the error occured\n", " message -- explaination of the error\n", " \"\"\"\n", " def __init__(self, expression, message):\n", " self.expression = expression\n", " self.message = message\n", " " ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on class InputError in module __main__:\n", "\n", "class InputError(builtins.Exception)\n", " | Exception raised for errors in the input.\n", " | \n", " | Attributes:\n", " | expression -- input expression in which the error occured\n", " | message -- explaination of the error\n", " | \n", " | Method resolution order:\n", " | InputError\n", " | builtins.Exception\n", " | builtins.BaseException\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __init__(self, expression, message)\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors defined here:\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from builtins.Exception:\n", " | \n", " | __new__(*args, **kwargs) from builtins.type\n", " | Create and return a new object. See help(type) for accurate signature.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from builtins.BaseException:\n", " | \n", " | __delattr__(self, name, /)\n", " | Implement delattr(self, name).\n", " | \n", " | __getattribute__(self, name, /)\n", " | Return getattr(self, name).\n", " | \n", " | __reduce__(...)\n", " | helper for pickle\n", " | \n", " | __repr__(self, /)\n", " | Return repr(self).\n", " | \n", " | __setattr__(self, name, value, /)\n", " | Implement setattr(self, name, value).\n", " | \n", " | __setstate__(...)\n", " | \n", " | __str__(self, /)\n", " | Return str(self).\n", " | \n", " | with_traceback(...)\n", " | Exception.with_traceback(tb) --\n", " | set self.__traceback__ to tb and return self.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from builtins.BaseException:\n", " | \n", " | __cause__\n", " | exception cause\n", " | \n", " | __context__\n", " | exception context\n", " | \n", " | __dict__\n", " | \n", " | __suppress_context__\n", " | \n", " | __traceback__\n", " | \n", " | args\n", "\n" ] } ], "source": [ "help(InputError)" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "def getInteger():\n", " x = input('Enter an integer number: ')\n", " if not x.isdigit():\n", " raise InputError(x, 'That is not an integer!')\n", " return int(x)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Enter an integer number: dsaf\n" ] }, { "ename": "InputError", "evalue": "('dsaf', 'That is not an integer!')", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mInputError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mgetInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m\u001b[0m in \u001b[0;36mgetInteger\u001b[0;34m()\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0minput\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Enter an integer number: '\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0misdigit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mInputError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'That is not an integer!'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 5\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mInputError\u001b[0m: ('dsaf', 'That is not an integer!')" ] } ], "source": [ "x = getInteger()\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "## catch user-defined exception" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Enter an integer number: 10\n", "10^2 = 100\n" ] } ], "source": [ "try:\n", " x = getInteger() #may throw InputError\n", "except InputError as ie:\n", " print('Exception:', ie)\n", " # can throw ie again\n", "else:\n", " print('{}^2 = {}'.format(x, x**2))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.3" } }, "nbformat": 4, "nbformat_minor": 2 }