{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# Software Entwicklung \n",
    "\n",
    "## Kapitel 7: Ausnahmebehandlung und Paketverwaltung"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### 7.1 Exceptions\n",
    "\n",
    "#### 7.1.1 Was sind Exceptions?\n",
    "\n",
    "Immer wieder treten bei der Ausführung von Python-Code Fehler auf. Das kann auf fehlerhafte\n",
    "Programmierung hindeuten, z.B. bei folgendem Code:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "liste = []\n",
    "print(liste[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Solche Programmierfehler sollten natürlich vermieden werden.\n",
    "\n",
    "Manchmal ist der Entwickler aber unschuldig, z.B. wenn der Plattenplatz zum Speichern nicht \n",
    "mehr ausreicht oder der Anwender ungültige Werte eingibt. Solche Laufzeitfehler führen zu\n",
    "Ausnahmen oder *Exceptions*."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "zaehler = int(input(\"Zähler: \"))\n",
    "nenner = int(input(\"Nenner: \"))\n",
    "print(zaehler/nenner)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Manche dieser Exceptions können auch durch vorheriges Überprüfen nicht vollständig\n",
    "ausgeschlossen werden (z.B. Abbruch einer Netzverbindung). Wie kann trotzdem verhindert werden,\n",
    "dass das Programm abbricht?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "#### 7.1.2 Fangen von Exceptions\n",
    "\n",
    "Ein Programmabruch kann verhindert werden, indem man den kritischen Codeblock mittels\n",
    "<code>try</code> absichert und anschließend mit <code>except</code> angibt, was im\n",
    "Falle einer Exception zu tun ist."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "try:\n",
    "    zaehler = int(input(\"Zähler: \"))\n",
    "    nenner = int(input(\"Nenner: \"))\n",
    "    print(zaehler/nenner)\n",
    "except:\n",
    "    print(\"Ungültige Eingaben!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Es ist auch möglich, genauere Informationen über die aufgetretene Exception zu erhalten, indem\n",
    "sie einer Variablen zugewiesen wird."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "try:\n",
    "    zaehler = int(input(\"Zähler: \"))\n",
    "    nenner = int(input(\"Nenner: \"))\n",
    "    print(zaehler/nenner)\n",
    "except Exception as e:\n",
    "    print(e.__class__)\n",
    "    print(e)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Möchte man unterschiedliche Behandlungen für unterschiedliche Exception-Klassen\n",
    "hinterlegen, so können mehrere <code>except</code>-Blöcke mit Angabe der Klasse\n",
    "verwendet werden."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "try:\n",
    "    zaehler = int(input(\"Zähler: \"))\n",
    "    nenner = int(input(\"Nenner: \"))\n",
    "    print(zaehler/nenner)\n",
    "except ValueError:\n",
    "    print(\"Sie haben keine ganze Zahl eingegeben\")\n",
    "except ZeroDivisionError:\n",
    "    print(\"Divison durch Null\")\n",
    "except:\n",
    "    print(\"Irgendwas anderes\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Die Programmausführung wird nach dem letzten <code>except</code> normal fortgesetzt.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "def division(z, n):\n",
    "    try:\n",
    "        zaehler = int(z)\n",
    "        nenner = int(n)\n",
    "        return zaehler / nenner\n",
    "    except:\n",
    "        print(\"Fehler!\")\n",
    "    return None\n",
    "\n",
    "division(1, 0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Gelegentlich möchte man nach dem <code>try</code>-Block noch Aufräumarbeiten durchführen\n",
    "ohne zu berücksichtigen, ob ein Fehler aufgetreten ist. Das kann durch <code>finally</code>\n",
    "erreicht werden."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "def division(z, n):\n",
    "    try:\n",
    "        zaehler = int(z)\n",
    "        nenner = int(n)\n",
    "        return zaehler / nenner\n",
    "    except:\n",
    "        print(\"Fehler!\")\n",
    "    finally:\n",
    "        print(\"Aufräumen\")\n",
    "    return None\n",
    "\n",
    "division(1, 2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Nach einem <code>try</code>-Block muss\n",
    "\n",
    "* entweder mindestens ein <code>except</code>-Block\n",
    "* oder der <code>finally</code>-Block\n",
    "* oder beides\n",
    "\n",
    "angegeben werden."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "#### 7.1.3 Werfen von Exceptions\n",
    "\n",
    "Gelegentlich möchte man auch selbst eine Exception auslösen, wenn man eine\n",
    "unzulässige Situation entdeckt. Der Python-Befehl hierzu lautet <code>raise</code>."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "def division(z, n):\n",
    "    if n == 0:\n",
    "        raise Exception(\"Division durch Null nicht erlaubt!\")\n",
    "    return z/n\n",
    "\n",
    "division(1, 0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Neben der allgemeinen <code>Exception</code> beinhaltet der Python-Standard noch eine\n",
    "Vielzahl weiterer [Exception-Klassen](https://docs.python.org/3/library/exceptions.html#exception-hierarchy),\n",
    "die auch beim Werfen einer Exception genutzt werden können."
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Slideshow",
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.9.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
