{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Errors in Python can be separated into *syntax errors* and *runtime errors*. Syntax errors are caused by eg. unpaired brackets, wrong indentation, etc. A program with syntax errors can not run at all. More frequent are run-time errors that arise from an improper use of a function, missing data, etc. Since Python is an interpreted, dynamically typed language, most errors will show up on the fly, as opposed to compiled languages, where many errors occur during compilation.\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Exceptions\n", "\n", "Exception is thrown when an error occurs. If we miss this exception (see below), the program interrupted. E.g. division by zero throws an `ZeroDivisionError` exception.\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "ename": "ZeroDivisionError", "evalue": "division by zero", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;36m1\u001b[0m\u001b[1;33m/\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;31mZeroDivisionError\u001b[0m: division by zero" ] } ], "source": [ "1/0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Catching exceptions\n", "\n", "If you do not want to interrupt the program at the moment of an exception, we can use a `try` - `except` block. It works so that the unsafe part of the code is placed under `try`, followed by an `except` block, which contains instructions in the case of an error (exception).\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Don't divide by zero!\n" ] } ], "source": [ "try:\n", " 1/0\n", "except:\n", " print(\"Don't divide by zero!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`except` used as above catches all exceptions. This is not usually a good practice. It is advised to catch only specific exceptions (those that are expected). To catch the division by zero one would write:\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Don't divide by zero!\n", "division by zero\n" ] } ], "source": [ "try:\n", " 1/0\n", "# the e variable will contain the exception\n", "except ZeroDivisionError as e:\n", " print(\"Don't divide by zero!\")\n", " print(e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Complete try-except block may also contain `else` and `finally` blocks, see [documentation](http://docs.python.org/2/reference/compound_stmts.html#try) . `finally` is especially useful for \"cleaning\", eg. to close a file etc.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Raising exceptions\n", "\n", "Exceptions can, of course, be also thrown in our code using the `raise` keyword. For example, checking the input of a function can be carried out like this:\n" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4! = 24\n" ] } ], "source": [ "def fact(n):\n", " \"\"\"Calculates the factorial\n", " \"\"\"\n", " from math import factorial\n", " try:\n", " # try to convert n to a number\n", " n = float(n)\n", " except ValueError as e:\n", " raise ValueError('{} is not a number'.format(repr(n)))\n", " # is n integer >= 0\n", " if not n.is_integer() or n < 0:\n", " raise ValueError(\"{} is not an integer >= 0\".format(n))\n", " return factorial(n)\n", "\n", "# let's test the function\n", "n = 4\n", "print('{}! = {}'.format(n, fact(n)))" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4.0! = 24\n", "0! = 1\n", "'zero' is not a number\n", "3.2 is not an integer >= 0\n", "-1.0 is not an integer >= 0\n" ] } ], "source": [ "# do the exeptions work?\n", "for n in (4.0, \"0\", \"zero\", 3.2, -1):\n", " try:\n", " print('{}! = {}'.format(n, fact(n)))\n", " # the Exception class covers almost any exception\n", " except Exception as e:\n", " print(e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Traceback\n", "\n", "The `traceback` module provides means to discover the exception origin. Let's demonstrate the `print_exc` function:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Traceback (most recent call last):\n", " File \"\", line 4, in \n", " fact(1.1)\n", " File \"\", line 12, in fact\n", " raise ValueError(\"{} is not an integer >= 0\".format(n))\n", "ValueError: 1.1 is not an integer >= 0\n" ] } ], "source": [ "import traceback, sys\n", "\n", "try:\n", " fact(1.1)\n", "except Exception:\n", " traceback.print_exc(file=sys.stdout)" ] } ], "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.4.3" } }, "nbformat": 4, "nbformat_minor": 0 }