From b60ddeb64417a9e17c27140b274b76ee24d95aaf Mon Sep 17 00:00:00 2001
From: Anna Meyer <annapmeyer95@gmail.com>
Date: Fri, 21 Jul 2023 11:29:56 -0500
Subject: [PATCH] lec 15 notes

---
 .../lec_14_comprehensions_notes.ipynb         |   52 +-
 .../lec_15_error_handling_notes.ipynb         | 1093 +++++++++++++++++
 2 files changed, 1135 insertions(+), 10 deletions(-)
 create mode 100644 sum23/lecture_materials/15_Errors/lec_15_error_handling_notes.ipynb

diff --git a/sum23/lecture_materials/14_Comprehensions/lec_14_comprehensions_notes.ipynb b/sum23/lecture_materials/14_Comprehensions/lec_14_comprehensions_notes.ipynb
index 1c61d62..b4dd87d 100644
--- a/sum23/lecture_materials/14_Comprehensions/lec_14_comprehensions_notes.ipynb
+++ b/sum23/lecture_materials/14_Comprehensions/lec_14_comprehensions_notes.ipynb
@@ -734,6 +734,9 @@
     "\n",
     "for tuple_item in scores_dict.items():\n",
     "    print(tuple_item)\n",
+    "    key = tuple_item[0]\n",
+    "    val = tuple_item[1]\n",
+    "    print(key,val)\n",
     "    \n",
     "print(\"--------------------\")\n",
     "\n",
@@ -796,14 +799,23 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 1,
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Original: {'Nov': 28, 'Dec': 20, 'Jan': 10, 'Feb': 14}\n",
+      "New dict: {'Nov': -2.2222222222222223, 'Dec': -6.666666666666667, 'Jan': -12.222222222222223, 'Feb': -10.0}\n"
+     ]
+    }
+   ],
    "source": [
     "madison_fahrenheit = {'Nov': 28,'Dec': 20, 'Jan': 10,'Feb': 14}\n",
     "print(\"Original:\", madison_fahrenheit)\n",
     "\n",
-    "madison_celsius = {key: ??? \\\n",
+    "madison_celsius = {key: 5 / 9 * (val - 32) \\\n",
     "                   for key, val in madison_fahrenheit.items()}\n",
     "print(\"New dict:\", madison_celsius)"
    ]
@@ -817,14 +829,23 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 2,
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Original: {'Bob': '32', 'Cindy': '45', 'Alice': '39', 'Unknown': 'None'}\n",
+      "New dict: {'Bob': 32, 'Cindy': 45, 'Alice': 39, 'Unknown': None}\n"
+     ]
+    }
+   ],
    "source": [
     "scores_dict = {\"Bob\": \"32\", \"Cindy\" : \"45\", \"Alice\": \"39\", \"Unknown\": \"None\"}\n",
     "print(\"Original:\", scores_dict)\n",
     "\n",
-    "updated_scores_dict = {???}\n",
+    "# updated_scores_dict = {???}\n",
     "                       \n",
     "# # step 1: add for statement\n",
     "# updated_scores_dict = { ??? for key, val in scores_dict.items() ???}\n",
@@ -833,8 +854,8 @@
     "# updated_scores_dict = { ??? if val.isdigit() else ??? for key, val in scores_dict.items()}\n",
     "\n",
     "# # step 3: fill in \"if\" and \"else\" values\n",
-    "# updated_scores_dict = {key: int(val) if val.isdigit() else None \\\n",
-    "#                        for key, val in scores_dict.items()}\n",
+    "updated_scores_dict = {key: int(val) if val.isdigit() else None \\\n",
+    "                       for key, val in scores_dict.items()}\n",
     "\n",
     "print(\"New dict:\", updated_scores_dict)"
    ]
@@ -848,9 +869,20 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 3,
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'Bob': 83, 'Cindy': 87, 'Alice': 90, 'Meena': 93}"
+      ]
+     },
+     "execution_count": 3,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
    "source": [
     "scores_dict = {\"Bob\": [18, 72, 61, 5, 83], \n",
     "               \"Cindy\" : [27, 11, 55, 73, 87], \n",
diff --git a/sum23/lecture_materials/15_Errors/lec_15_error_handling_notes.ipynb b/sum23/lecture_materials/15_Errors/lec_15_error_handling_notes.ipynb
new file mode 100644
index 0000000..7713f92
--- /dev/null
+++ b/sum23/lecture_materials/15_Errors/lec_15_error_handling_notes.ipynb
@@ -0,0 +1,1093 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Error handling"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# import statements\n",
+    "import math"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Warmup\n",
+    "\n",
+    "### Warmup 1: How does this recursion work? Try it in Python tutor"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def chop(s):\n",
+    "    if len(s) < 3:\n",
+    "        return s[0]\n",
+    "    else:\n",
+    "        return s[1] + chop(s[2:])\n",
+    "\n",
+    "chop(\"abcdefghijklmnop\")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Now, by hand, figure out this output\n",
+    "chop(\"987654\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Lecture 25: Error Handling\n",
+    "\n",
+    "**Learing Objectives:**\n",
+    "    \n",
+    "- Explain the purpose of assert statements, try/except blocks, and raise statements.\n",
+    "\n",
+    "- Use an assert statement to force a program to crash, and trace code that uses assert.\n",
+    "\n",
+    "- Use try/except blocks to catch runtime errors and deal with them\n",
+    " - by specifying the exception(s) caught\n",
+    " - by using the exception object\n",
+    "\n",
+    "- Use the raise statement to raise an exception that may be caught in another part of the program\n",
+    "\n",
+    "- Hand trace code that uses assert, try/except blocks and raise statements\n",
+    "\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Why might you want your code to crash more?\n",
+    "\n",
+    "- It is easier to debug the program if we get a stack trace\n",
+    "- Semantic errors are the scariest because we don't get any kind of error\n",
+    "\n",
+    "### When is it fine for your code to crash less?\n",
+    "\n",
+    "- When user enters incorrect input, we simply want to display an error message and not crash\n",
+    "- When the program has syntax error, we definitely want the program to crash\n",
+    "\n",
+    "<div>\n",
+    "<img src=\"attachment:Theme.png\" width=\"600\"/>\n",
+    "</div>"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Pizza Analyzer"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def pizza_size(radius):\n",
+    "    return (radius ** 2) * math.pi\n",
+    "\n",
+    "def slice_size(radius, slice_count):\n",
+    "    total_size = pizza_size(radius)\n",
+    "    return total_size * (1 / slice_count)\n",
+    "\n",
+    "def main():\n",
+    "    for i in range(3):\n",
+    "        # grab input\n",
+    "        args = input(\"Enter pizza diameter(inches), slice count: \")\n",
+    "        args = args.split(',')\n",
+    "        radius = float(args[0].strip()) / 2\n",
+    "        slices = int(args[1].strip())\n",
+    "\n",
+    "        # pizza analysis\n",
+    "        size = slice_size(radius, slices)\n",
+    "        print('PIZZA: radius = {}, slices = {}, slice square inches = {}'\n",
+    "              .format(radius, slices, size))"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Try valid input of 4, 4 for main invocation"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Enter pizza diameter(inches), slice count: 4,4\n",
+      "PIZZA: radius = 2.0, slices = 4, slice square inches = 3.141592653589793\n",
+      "Enter pizza diameter(inches), slice count: 10,0\n"
+     ]
+    },
+    {
+     "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)",
+      "Cell \u001b[0;32mIn[3], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mmain\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
+      "Cell \u001b[0;32mIn[2], line 17\u001b[0m, in \u001b[0;36mmain\u001b[0;34m()\u001b[0m\n\u001b[1;32m     14\u001b[0m slices \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mint\u001b[39m(args[\u001b[38;5;241m1\u001b[39m]\u001b[38;5;241m.\u001b[39mstrip())\n\u001b[1;32m     16\u001b[0m \u001b[38;5;66;03m# pizza analysis\u001b[39;00m\n\u001b[0;32m---> 17\u001b[0m size \u001b[38;5;241m=\u001b[39m \u001b[43mslice_size\u001b[49m\u001b[43m(\u001b[49m\u001b[43mradius\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mslices\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m     18\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mPIZZA: radius = \u001b[39m\u001b[38;5;132;01m{}\u001b[39;00m\u001b[38;5;124m, slices = \u001b[39m\u001b[38;5;132;01m{}\u001b[39;00m\u001b[38;5;124m, slice square inches = \u001b[39m\u001b[38;5;132;01m{}\u001b[39;00m\u001b[38;5;124m'\u001b[39m\n\u001b[1;32m     19\u001b[0m       \u001b[38;5;241m.\u001b[39mformat(radius, slices, size))\n",
+      "Cell \u001b[0;32mIn[2], line 6\u001b[0m, in \u001b[0;36mslice_size\u001b[0;34m(radius, slice_count)\u001b[0m\n\u001b[1;32m      4\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mslice_size\u001b[39m(radius, slice_count):\n\u001b[1;32m      5\u001b[0m     total_size \u001b[38;5;241m=\u001b[39m pizza_size(radius)\n\u001b[0;32m----> 6\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m total_size \u001b[38;5;241m*\u001b[39m (\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m/\u001b[39;49m\u001b[43m \u001b[49m\u001b[43mslice_count\u001b[49m)\n",
+      "\u001b[0;31mZeroDivisionError\u001b[0m: division by zero"
+     ]
+    }
+   ],
+   "source": [
+    "main()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Can you think of any inputs that will make this program crash?\n",
+    "\n",
+    "Try each of these bad inputs:\n",
+    "- 10, 0: ZeroDivisionError\n",
+    "- 10: IndexError\n",
+    "- 10, hello: ValueError\n",
+    "- 10, 4.5: ValueError\n",
+    "- 10, -4: Semantic error\n",
+    "- -10, 4: Semantic error (scariest error for this example)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Enter pizza diameter(inches), slice count: 10, hi!\n"
+     ]
+    },
+    {
+     "ename": "ValueError",
+     "evalue": "invalid literal for int() with base 10: 'hi!'",
+     "output_type": "error",
+     "traceback": [
+      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
+      "Cell \u001b[0;32mIn[4], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mmain\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
+      "Cell \u001b[0;32mIn[2], line 14\u001b[0m, in \u001b[0;36mmain\u001b[0;34m()\u001b[0m\n\u001b[1;32m     12\u001b[0m args \u001b[38;5;241m=\u001b[39m args\u001b[38;5;241m.\u001b[39msplit(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m,\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m     13\u001b[0m radius \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mfloat\u001b[39m(args[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39mstrip()) \u001b[38;5;241m/\u001b[39m \u001b[38;5;241m2\u001b[39m\n\u001b[0;32m---> 14\u001b[0m slices \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mint\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43margs\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m]\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mstrip\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m     16\u001b[0m \u001b[38;5;66;03m# pizza analysis\u001b[39;00m\n\u001b[1;32m     17\u001b[0m size \u001b[38;5;241m=\u001b[39m slice_size(radius, slices)\n",
+      "\u001b[0;31mValueError\u001b[0m: invalid literal for int() with base 10: 'hi!'"
+     ]
+    }
+   ],
+   "source": [
+    "main()\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Enter pizza diameter(inches), slice count: -10, 4\n",
+      "PIZZA: radius = -5.0, slices = 4, slice square inches = 19.634954084936208\n"
+     ]
+    },
+    {
+     "ename": "KeyboardInterrupt",
+     "evalue": "Interrupted by user",
+     "output_type": "error",
+     "traceback": [
+      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[0;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
+      "Cell \u001b[0;32mIn[6], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mmain\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
+      "Cell \u001b[0;32mIn[2], line 11\u001b[0m, in \u001b[0;36mmain\u001b[0;34m()\u001b[0m\n\u001b[1;32m      8\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mmain\u001b[39m():\n\u001b[1;32m      9\u001b[0m     \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(\u001b[38;5;241m3\u001b[39m):\n\u001b[1;32m     10\u001b[0m         \u001b[38;5;66;03m# grab input\u001b[39;00m\n\u001b[0;32m---> 11\u001b[0m         args \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43minput\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mEnter pizza diameter(inches), slice count: \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m     12\u001b[0m         args \u001b[38;5;241m=\u001b[39m args\u001b[38;5;241m.\u001b[39msplit(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m,\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m     13\u001b[0m         radius \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mfloat\u001b[39m(args[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39mstrip()) \u001b[38;5;241m/\u001b[39m \u001b[38;5;241m2\u001b[39m\n",
+      "File \u001b[0;32m~/miniforge3/lib/python3.10/site-packages/ipykernel/kernelbase.py:1191\u001b[0m, in \u001b[0;36mKernel.raw_input\u001b[0;34m(self, prompt)\u001b[0m\n\u001b[1;32m   1189\u001b[0m     msg \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mraw_input was called, but this frontend does not support input requests.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m   1190\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m StdinNotImplementedError(msg)\n\u001b[0;32m-> 1191\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_input_request\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m   1192\u001b[0m \u001b[43m    \u001b[49m\u001b[38;5;28;43mstr\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mprompt\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m   1193\u001b[0m \u001b[43m    \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_parent_ident\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mshell\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m   1194\u001b[0m \u001b[43m    \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_parent\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mshell\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m   1195\u001b[0m \u001b[43m    \u001b[49m\u001b[43mpassword\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m   1196\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n",
+      "File \u001b[0;32m~/miniforge3/lib/python3.10/site-packages/ipykernel/kernelbase.py:1234\u001b[0m, in \u001b[0;36mKernel._input_request\u001b[0;34m(self, prompt, ident, parent, password)\u001b[0m\n\u001b[1;32m   1231\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m:\n\u001b[1;32m   1232\u001b[0m     \u001b[38;5;66;03m# re-raise KeyboardInterrupt, to truncate traceback\u001b[39;00m\n\u001b[1;32m   1233\u001b[0m     msg \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mInterrupted by user\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m-> 1234\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m(msg) \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m   1235\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m:\n\u001b[1;32m   1236\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlog\u001b[38;5;241m.\u001b[39mwarning(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mInvalid Message:\u001b[39m\u001b[38;5;124m\"\u001b[39m, exc_info\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\n",
+      "\u001b[0;31mKeyboardInterrupt\u001b[0m: Interrupted by user"
+     ]
+    }
+   ],
+   "source": [
+    "main()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### What was the scariest error in the above examples?"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# - -10, 4: Semantic error (scariest error for this example)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## `assert` statements\n",
+    "- `assert` statements enable you to convert semantic errors into runtime errors\n",
+    "    - runtime errors are easier to debug than semantic errors\n",
+    "- `assert` statements make your program very slow!\n",
+    "    - so sometimes programmers disable these (we won't be learning about this)\n",
+    "- Syntax: `assert BOOLEAN_EXPRESSION`\n",
+    "    - BOOLEAN_EXPRESSION evaluates to `True`: nothing happens (move on to next line of code)\n",
+    "    - BOOLEAN_EXPRESSION evaluates to `False`: program carshes with `AssertionError`\n",
+    "       \n",
+    "<div>\n",
+    "<img src=\"attachment:Assert.png\" width=\"450\"/>\n",
+    "</div>"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Enter your age: -5\n"
+     ]
+    },
+    {
+     "ename": "AssertionError",
+     "evalue": "",
+     "output_type": "error",
+     "traceback": [
+      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[0;31mAssertionError\u001b[0m                            Traceback (most recent call last)",
+      "Cell \u001b[0;32mIn[8], line 4\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[38;5;66;03m# simple example\u001b[39;00m\n\u001b[1;32m      3\u001b[0m age \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mint\u001b[39m(\u001b[38;5;28minput\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mEnter your age: \u001b[39m\u001b[38;5;124m\"\u001b[39m))\n\u001b[0;32m----> 4\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m age \u001b[38;5;241m>\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0\u001b[39m \u001b[38;5;66;03m# if True, do nothing else, crash\u001b[39;00m\n\u001b[1;32m      5\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mIn five years you will be\u001b[39m\u001b[38;5;124m\"\u001b[39m, age \u001b[38;5;241m+\u001b[39m \u001b[38;5;241m5\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124myears old\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n",
+      "\u001b[0;31mAssertionError\u001b[0m: "
+     ]
+    }
+   ],
+   "source": [
+    "# simple example\n",
+    "\n",
+    "age = int(input(\"Enter your age: \"))\n",
+    "assert age >= 0 # if True, do nothing else, crash\n",
+    "print(\"In five years you will be\", age + 5, \"years old\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "<div>\n",
+    "<img src=\"attachment:assert.png\" width=\"600\"/>\n",
+    "</div>"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Let's improvise error handling in pizza analyzer\n",
+    "- using `assert`:\n",
+    "    - `assert` that radius is positive\n",
+    "    - `assert` that slice count is positive"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 14,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Copy pasted code (not a typical thing which I will ask you to do) \n",
+    "# change function definitions to v2 and add the assert statements\n",
+    "\n",
+    "def pizza_size_v2(radius):\n",
+    "    # TODO add assert statement here\n",
+    "    assert radius >= 0\n",
+    "    return (radius ** 2) * math.pi\n",
+    "\n",
+    "def slice_size_v2(radius, slice_count):\n",
+    "    # TODO add assert statement here\n",
+    "    assert slice_count >= 1\n",
+    "    total_size = pizza_size_v2(radius)\n",
+    "    return total_size * (1 / slice_count)\n",
+    "\n",
+    "def main_v2():\n",
+    "    for i in range(3):\n",
+    "        # grab input\n",
+    "        args = input(\"Enter pizza diameter(inches), slice count: \")\n",
+    "        args = args.split(',')\n",
+    "        radius = float(args[0].strip()) / 2\n",
+    "        slices = int(args[1].strip())\n",
+    "\n",
+    "        # pizza analysis\n",
+    "        size = slice_size_v2(radius, slices)\n",
+    "        print('PIZZA: radius = {}, slices = {}, slice square inches = {}'\n",
+    "              .format(radius, slices, size))"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Try these problematic inputs for the main() function invocation\n",
+    "\n",
+    "- 10, -4: Semantic error\n",
+    "- -10, 4: Semantic error (scariest error for this example)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 15,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Enter pizza diameter(inches), slice count: -10, 4\n"
+     ]
+    },
+    {
+     "ename": "AssertionError",
+     "evalue": "",
+     "output_type": "error",
+     "traceback": [
+      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[0;31mAssertionError\u001b[0m                            Traceback (most recent call last)",
+      "Cell \u001b[0;32mIn[15], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mmain_v2\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
+      "Cell \u001b[0;32mIn[14], line 24\u001b[0m, in \u001b[0;36mmain_v2\u001b[0;34m()\u001b[0m\n\u001b[1;32m     21\u001b[0m slices \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mint\u001b[39m(args[\u001b[38;5;241m1\u001b[39m]\u001b[38;5;241m.\u001b[39mstrip())\n\u001b[1;32m     23\u001b[0m \u001b[38;5;66;03m# pizza analysis\u001b[39;00m\n\u001b[0;32m---> 24\u001b[0m size \u001b[38;5;241m=\u001b[39m \u001b[43mslice_size_v2\u001b[49m\u001b[43m(\u001b[49m\u001b[43mradius\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mslices\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m     25\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mPIZZA: radius = \u001b[39m\u001b[38;5;132;01m{}\u001b[39;00m\u001b[38;5;124m, slices = \u001b[39m\u001b[38;5;132;01m{}\u001b[39;00m\u001b[38;5;124m, slice square inches = \u001b[39m\u001b[38;5;132;01m{}\u001b[39;00m\u001b[38;5;124m'\u001b[39m\n\u001b[1;32m     26\u001b[0m       \u001b[38;5;241m.\u001b[39mformat(radius, slices, size))\n",
+      "Cell \u001b[0;32mIn[14], line 12\u001b[0m, in \u001b[0;36mslice_size_v2\u001b[0;34m(radius, slice_count)\u001b[0m\n\u001b[1;32m      9\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mslice_size_v2\u001b[39m(radius, slice_count):\n\u001b[1;32m     10\u001b[0m     \u001b[38;5;66;03m# TODO add assert statement here\u001b[39;00m\n\u001b[1;32m     11\u001b[0m     \u001b[38;5;28;01massert\u001b[39;00m slice_count \u001b[38;5;241m>\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[0;32m---> 12\u001b[0m     total_size \u001b[38;5;241m=\u001b[39m \u001b[43mpizza_size_v2\u001b[49m\u001b[43m(\u001b[49m\u001b[43mradius\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m     13\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m total_size \u001b[38;5;241m*\u001b[39m (\u001b[38;5;241m1\u001b[39m \u001b[38;5;241m/\u001b[39m slice_count)\n",
+      "Cell \u001b[0;32mIn[14], line 6\u001b[0m, in \u001b[0;36mpizza_size_v2\u001b[0;34m(radius)\u001b[0m\n\u001b[1;32m      4\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mpizza_size_v2\u001b[39m(radius):\n\u001b[1;32m      5\u001b[0m     \u001b[38;5;66;03m# TODO add assert statement here\u001b[39;00m\n\u001b[0;32m----> 6\u001b[0m     \u001b[38;5;28;01massert\u001b[39;00m radius \u001b[38;5;241m>\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0\u001b[39m\n\u001b[1;32m      7\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m (radius \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39m \u001b[38;5;241m2\u001b[39m) \u001b[38;5;241m*\u001b[39m math\u001b[38;5;241m.\u001b[39mpi\n",
+      "\u001b[0;31mAssertionError\u001b[0m: "
+     ]
+    }
+   ],
+   "source": [
+    "main_v2()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## What if we want to keep running even if there is an error?\n",
+    "\n",
+    "That is, we don't want to pause the program execution for user's incorrect input"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## try / except blocks\n",
+    "\n",
+    "- `try` and `except` blocks come in pairs (runtime errors are “exceptions”)\n",
+    "- Python tries to run the code in the `try` block.  \n",
+    "    - If there is an exception, `try` block execution terminates and then `except` block gets executed(instead of crashing). This is called “catching” the exception.\n",
+    "    - If there is no exception, `except` block doesn't get executed.\n",
+    "- Syntax (example):\n",
+    "```python\n",
+    "try:\n",
+    "    flaky_function()\n",
+    "except:\n",
+    "    print(\"error!\") # or some other handling\n",
+    "```"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### try / except examples\n",
+    "Try these examples using PythonTutor"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Example 1: v1"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "try:\n",
+    "    print(\"2 inverse is\", 1/2)\n",
+    "    print(\"1 inverse is\", 1/1)\n",
+    "    print(\"0 inverse is\", 1/0)\n",
+    "    print(\"-1 inverse is\", -1/1)\n",
+    "    print(\"-2 inverse is\", -1/1)\n",
+    "except:\n",
+    "    print(\"that's all, folks!\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Example 1: v2"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 16,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "2 inverse is 0.5\n",
+      "1 inverse is 1.0\n",
+      "that's all, folks!\n",
+      "-1 inverse is -1.0\n",
+      "-2 inverse is -1.0\n"
+     ]
+    }
+   ],
+   "source": [
+    "try:\n",
+    "    print(\"2 inverse is\", 1/2)\n",
+    "    print(\"1 inverse is\", 1/1)\n",
+    "    print(\"0 inverse is\", 1/0)\n",
+    "except:\n",
+    "    print(\"that's all, folks!\")\n",
+    "\n",
+    "try:\n",
+    "    print(\"-1 inverse is\", -1/1)\n",
+    "    print(\"-2 inverse is\", -1/1)\n",
+    "except:\n",
+    "    print(\"This will never get executed!\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Example 2: v1\n",
+    "- hierarchy of catching exceptions"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 17,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "f: let's call g\n",
+      "g: before buggy\n",
+      "buggy: about to fail\n",
+      "f: that didn't go so well\n"
+     ]
+    }
+   ],
+   "source": [
+    "def buggy():\n",
+    "    print(\"buggy: about to fail\")\n",
+    "    print(\"buggy: infinity is \", 1/0)\n",
+    "    print(\"buggy: oops!\") # never prints\n",
+    "\n",
+    "def g():\n",
+    "    print(\"g: before buggy\")\n",
+    "    buggy()\n",
+    "    print(\"g: after buggy\") # never prints\n",
+    "\n",
+    "def f():\n",
+    "    try:\n",
+    "        print(\"f: let's call g\")\n",
+    "        g()\n",
+    "        print(\"f: g returned normally\") # never prints\n",
+    "    except:\n",
+    "        print(\"f: that didn't go so well\")\n",
+    "\n",
+    "f()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Example 2: v2\n",
+    "- hierarchy of catching exceptions"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 18,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "f: let's call g\n",
+      "g: before buggy\n",
+      "buggy: about to fail\n",
+      "g: that didn't go well\n",
+      "g: after buggy\n",
+      "f: g returned normally\n"
+     ]
+    }
+   ],
+   "source": [
+    "def buggy():\n",
+    "    print(\"buggy: about to fail\")\n",
+    "    print(\"buggy: infinity is \", 1/0)\n",
+    "    print(\"buggy: oops!\") # never prints\n",
+    "\n",
+    "def g():\n",
+    "    print(\"g: before buggy\")\n",
+    "    try:\n",
+    "        buggy()\n",
+    "    except:\n",
+    "        print(\"g: that didn't go well\")\n",
+    "    print(\"g: after buggy\") \n",
+    "\n",
+    "def f():\n",
+    "    try:\n",
+    "        print(\"f: let's call g\")\n",
+    "        g()\n",
+    "        print(\"f: g returned normally\") \n",
+    "    except:\n",
+    "        print(\"f: that didn't go so well\") # never prints\n",
+    "\n",
+    "f()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Example 2: v3\n",
+    "- hierarchy of catching exceptions"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 19,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "f: let's call g\n",
+      "g: before buggy\n",
+      "buggy: about to fail\n",
+      "buggy: oops!\n",
+      "g: after buggy\n",
+      "f: g returned normally\n"
+     ]
+    }
+   ],
+   "source": [
+    "def buggy():\n",
+    "    try:\n",
+    "        print(\"buggy: about to fail\")\n",
+    "        print(\"buggy: infinity is \", 1/0)\n",
+    "    except:\n",
+    "        print(\"buggy: oops!\") \n",
+    "\n",
+    "def g():\n",
+    "    print(\"g: before buggy\")\n",
+    "    try:\n",
+    "        buggy()\n",
+    "    except:\n",
+    "        print(\"g: that didn't go well\") # never prints\n",
+    "    print(\"g: after buggy\")\n",
+    "\n",
+    "def f():\n",
+    "    try:\n",
+    "        print(\"f: let's call g\")\n",
+    "        g()\n",
+    "        print(\"f: g returned normally\") \n",
+    "    except:\n",
+    "        print(\"f: that didn't go so well\") # never prints\n",
+    "\n",
+    "f()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### What if we want to know the reason for the exception?\n",
+    "\n",
+    "- Syntax (example):\n",
+    "```python\n",
+    "try:\n",
+    "    flaky_function()\n",
+    "except Exception as e:\n",
+    "    print(\"error because:\", str(e))\n",
+    "    print(\"type of exception:\", type(e))\n",
+    "```\n",
+    "- `Exception` is a type.\n",
+    "- e an object instance of of type `Exception` (very general)\n",
+    "    - there are different types of exceptions\n",
+    "- `str(e)` gives you the reason for the exception.\n",
+    "- `type(e)` will give you the type of the exception."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Let's improvise error handling in pizza analyzer more\n",
+    "- using `try` ... `except` ... "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 24,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def main_v3():\n",
+    "    for i in range(3):\n",
+    "        # grab input\n",
+    "        args = input(\"Enter pizza diameter(inches), slice count: \")\n",
+    "        args = args.split(',')\n",
+    "\n",
+    "\n",
+    "        # pizza analysis TODO add try/except here\n",
+    "        try:\n",
+    "            radius = float(args[0].strip()) / 2\n",
+    "            slices = int(args[1].strip())\n",
+    "            size = slice_size_v2(radius, slices)\n",
+    "            print('PIZZA: radius = {}, slices = {}, slice square inches = {}'\n",
+    "              .format(radius, slices, size))\n",
+    "        except Exception as e:\n",
+    "            print(\"error because: \",str(e))\n",
+    "            print(\"type of error: \", type(e))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Try these problematic inputs for the main() function invocation\n",
+    "\n",
+    "- 10, 0: ZeroDivisionError\n",
+    "- 10: IndexError\n",
+    "- 10, hello: ValueError\n",
+    "- 10, 4.5: ValueError\n",
+    "- 10, -4: AssertionError (after we wrote assert statement)\n",
+    "- -10, 4: AssertionError (after we wrote assert statement)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 25,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Enter pizza diameter(inches), slice count: 10,4.5\n",
+      "error because:  invalid literal for int() with base 10: '4.5'\n",
+      "type of error:  <class 'ValueError'>\n",
+      "Enter pizza diameter(inches), slice count: 10, -4\n",
+      "error because:  \n",
+      "type of error:  <class 'AssertionError'>\n",
+      "Enter pizza diameter(inches), slice count: 10, 0\n",
+      "error because:  \n",
+      "type of error:  <class 'AssertionError'>\n"
+     ]
+    }
+   ],
+   "source": [
+    "main_v3()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### `Exception` is too broad\n",
+    "- it catches many types of exceptions\n",
+    "- you do not want your except block to catch every possible exception!"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 26,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Let's create an intentional SyntaxError\n",
+    "\n",
+    "def main_v4():\n",
+    "    for i in range(5):\n",
+    "        try:\n",
+    "            # grab input\n",
+    "            args = input(\"Enter pizza diameter(inches), slice count: \")\n",
+    "            args = argssssss.split(',')\n",
+    "            radius = float(args[0].strip()) / 2\n",
+    "            slices = int(args[1].strip())\n",
+    "        except Exception as e:\n",
+    "            print(\"Bad input & reason is:\", str(e))\n",
+    "            print(\"Type of exception:\", type(e))\n",
+    "            \n",
+    "        try:\n",
+    "            # pizza analysis\n",
+    "            size = slice_size_v2(radius, slices)\n",
+    "            print('PIZZA: radius = {}, slices = {}, slice square inches = {}'\n",
+    "                  .format(radius, slices, size))\n",
+    "        except Exception as e:\n",
+    "            print(\"Pizza analysis error & reason is:\", str(e))\n",
+    "            print(\"Type of exception:\", type(e))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 27,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Enter pizza diameter(inches), slice count: 10,4\n",
+      "Bad input & reason is: name 'argssssss' is not defined\n",
+      "Type of exception: <class 'NameError'>\n",
+      "Pizza analysis error & reason is: local variable 'radius' referenced before assignment\n",
+      "Type of exception: <class 'UnboundLocalError'>\n"
+     ]
+    },
+    {
+     "ename": "KeyboardInterrupt",
+     "evalue": "Interrupted by user",
+     "output_type": "error",
+     "traceback": [
+      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[0;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
+      "Cell \u001b[0;32mIn[27], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mmain_v4\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;66;03m# oops, we made our program way too robus!\u001b[39;00m\n",
+      "Cell \u001b[0;32mIn[26], line 7\u001b[0m, in \u001b[0;36mmain_v4\u001b[0;34m()\u001b[0m\n\u001b[1;32m      4\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(\u001b[38;5;241m5\u001b[39m):\n\u001b[1;32m      5\u001b[0m     \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m      6\u001b[0m         \u001b[38;5;66;03m# grab input\u001b[39;00m\n\u001b[0;32m----> 7\u001b[0m         args \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43minput\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mEnter pizza diameter(inches), slice count: \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m      8\u001b[0m         args \u001b[38;5;241m=\u001b[39m argssssss\u001b[38;5;241m.\u001b[39msplit(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m,\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m      9\u001b[0m         radius \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mfloat\u001b[39m(args[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39mstrip()) \u001b[38;5;241m/\u001b[39m \u001b[38;5;241m2\u001b[39m\n",
+      "File \u001b[0;32m~/miniforge3/lib/python3.10/site-packages/ipykernel/kernelbase.py:1191\u001b[0m, in \u001b[0;36mKernel.raw_input\u001b[0;34m(self, prompt)\u001b[0m\n\u001b[1;32m   1189\u001b[0m     msg \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mraw_input was called, but this frontend does not support input requests.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m   1190\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m StdinNotImplementedError(msg)\n\u001b[0;32m-> 1191\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_input_request\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m   1192\u001b[0m \u001b[43m    \u001b[49m\u001b[38;5;28;43mstr\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mprompt\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m   1193\u001b[0m \u001b[43m    \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_parent_ident\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mshell\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m   1194\u001b[0m \u001b[43m    \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_parent\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mshell\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m   1195\u001b[0m \u001b[43m    \u001b[49m\u001b[43mpassword\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m   1196\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n",
+      "File \u001b[0;32m~/miniforge3/lib/python3.10/site-packages/ipykernel/kernelbase.py:1234\u001b[0m, in \u001b[0;36mKernel._input_request\u001b[0;34m(self, prompt, ident, parent, password)\u001b[0m\n\u001b[1;32m   1231\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m:\n\u001b[1;32m   1232\u001b[0m     \u001b[38;5;66;03m# re-raise KeyboardInterrupt, to truncate traceback\u001b[39;00m\n\u001b[1;32m   1233\u001b[0m     msg \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mInterrupted by user\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m-> 1234\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m(msg) \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m   1235\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m:\n\u001b[1;32m   1236\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlog\u001b[38;5;241m.\u001b[39mwarning(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mInvalid Message:\u001b[39m\u001b[38;5;124m\"\u001b[39m, exc_info\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\n",
+      "\u001b[0;31mKeyboardInterrupt\u001b[0m: Interrupted by user"
+     ]
+    }
+   ],
+   "source": [
+    "main_v4() # oops, we made our program way too robus!\n",
+    "\n",
+    "# In this case, it's a syntax error, so the program will never work\n",
+    "# We want the program to crash so that we know we have to fix it"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### How can we make `except` block catch specific exceptions?\n",
+    "\n",
+    "- Syntax (example):\n",
+    "```python\n",
+    "try:\n",
+    "    flaky_function()\n",
+    "except (ValueError, IndexError) as e:\n",
+    "    print(\"error because:\", str(e))\n",
+    "    print(\"type of exception:\", type(e))\n",
+    "```"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 30,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Let's fix our except blocks\n",
+    "# Try introducing the intentional SyntaxError now\n",
+    "\n",
+    "def main_v5():\n",
+    "    for i in range(5):\n",
+    "        try:\n",
+    "            # grab input\n",
+    "            args = input(\"Enter pizza diameter(inches), slice count: \")\n",
+    "            args = argssssssss.split(',')\n",
+    "            radius = float(args[0].strip()) / 2\n",
+    "            slices = int(args[1].strip())\n",
+    "        except (ValueError, IndexError) as e:\n",
+    "            print(\"Bad input & reason is:\", str(e))\n",
+    "            print(\"Type of exception:\", type(e))\n",
+    "            continue\n",
+    "            \n",
+    "        try:\n",
+    "            # pizza analysis\n",
+    "            size = slice_size_v2(radius, slices)\n",
+    "            print('PIZZA: radius = {}, slices = {}, slice square inches = {}'\n",
+    "                  .format(radius, slices, size))\n",
+    "        except Exception as e:\n",
+    "            print(\"Pizza analysis error & reason is:\", str(e))\n",
+    "            print(\"Type of exception:\", type(e))"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Try these problematic inputs for the main() function invocation\n",
+    "\n",
+    "- 10, 0: ZeroDivisionError\n",
+    "- 10: IndexError\n",
+    "- 10, hello: ValueError\n",
+    "- 10, 4.5: ValueError\n",
+    "- 10, -4: AssertionError (after we wrote assert statement)\n",
+    "- -10, 4: AssertionError (after we wrote assert statement)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 31,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Enter pizza diameter(inches), slice count: 10,4.5\n"
+     ]
+    },
+    {
+     "ename": "NameError",
+     "evalue": "name 'argssssssss' is not defined",
+     "output_type": "error",
+     "traceback": [
+      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
+      "Cell \u001b[0;32mIn[31], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mmain_v5\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
+      "Cell \u001b[0;32mIn[30], line 9\u001b[0m, in \u001b[0;36mmain_v5\u001b[0;34m()\u001b[0m\n\u001b[1;32m      6\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m      7\u001b[0m     \u001b[38;5;66;03m# grab input\u001b[39;00m\n\u001b[1;32m      8\u001b[0m     args \u001b[38;5;241m=\u001b[39m \u001b[38;5;28minput\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mEnter pizza diameter(inches), slice count: \u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m----> 9\u001b[0m     args \u001b[38;5;241m=\u001b[39m \u001b[43margssssssss\u001b[49m\u001b[38;5;241m.\u001b[39msplit(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m,\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m     10\u001b[0m     radius \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mfloat\u001b[39m(args[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39mstrip()) \u001b[38;5;241m/\u001b[39m \u001b[38;5;241m2\u001b[39m\n\u001b[1;32m     11\u001b[0m     slices \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mint\u001b[39m(args[\u001b[38;5;241m1\u001b[39m]\u001b[38;5;241m.\u001b[39mstrip())\n",
+      "\u001b[0;31mNameError\u001b[0m: name 'argssssssss' is not defined"
+     ]
+    }
+   ],
+   "source": [
+    "main_v5()\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Exception hierarchy\n",
+    "- It helps to know some common excpeptions and to know their hierarchy.\n",
+    "- Don't try to memorize this but do make a note of the exceptions that occur the most often.\n",
+    "- Python documentation: https://docs.python.org/3/library/exceptions.html."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### `raise` statements\n",
+    "- Rather than using assert we can also raise a specific error. \n",
+    "\n",
+    "- Syntax (example):\n",
+    "```python\n",
+    "if BOOLEAN_CONDITION:\n",
+    "    raise ArithmeticError(\"details of error\")\n",
+    "```\n",
+    "\n",
+    "<div>\n",
+    "<img src=\"attachment:raise.png\" width=\"500\"/>\n",
+    "</div>"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 32,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "enter your age: -5\n"
+     ]
+    },
+    {
+     "ename": "ArithmeticError",
+     "evalue": "age can't be negative",
+     "output_type": "error",
+     "traceback": [
+      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[0;31mArithmeticError\u001b[0m                           Traceback (most recent call last)",
+      "Cell \u001b[0;32mIn[32], line 6\u001b[0m\n\u001b[1;32m      4\u001b[0m \u001b[38;5;66;03m# previously: assert a >= 0\u001b[39;00m\n\u001b[1;32m      5\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m age \u001b[38;5;241m<\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[0;32m----> 6\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mArithmeticError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mage can\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mt be negative\u001b[39m\u001b[38;5;124m\"\u001b[39m) \u001b[38;5;66;03m# we can 'raise' a relevant exception\u001b[39;00m\n\u001b[1;32m      7\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124min five years you will be\u001b[39m\u001b[38;5;124m\"\u001b[39m, age \u001b[38;5;241m+\u001b[39m \u001b[38;5;241m5\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124myears old\u001b[39m\u001b[38;5;124m\"\u001b[39m) \n",
+      "\u001b[0;31mArithmeticError\u001b[0m: age can't be negative"
+     ]
+    }
+   ],
+   "source": [
+    "# simple example: raise exceptions instead of using assert statements\n",
+    "\n",
+    "age = int(input(\"enter your age: \"))\n",
+    "# previously: assert a >= 0\n",
+    "if age < 0:\n",
+    "    raise ArithmeticError(\"age can't be negative\") # we can 'raise' a relevant exception\n",
+    "print(\"in five years you will be\", age + 5, \"years old\") "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 33,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "\n",
+    "def pizza_size_v2(radius):\n",
+    "    assert radius >= 0\n",
+    "    return (radius ** 2) * math.pi\n",
+    "\n",
+    "def slice_size_v2(radius, slice_count):\n",
+    "    assert slice_count >= 0\n",
+    "    total_size = pizza_size_v2(radius)\n",
+    "    return total_size * (1 / slice_count)\n",
+    "\n",
+    "def main_v6():\n",
+    "    for i in range(5):\n",
+    "        # grab input\n",
+    "        try:\n",
+    "            args = input(\"Enter pizza diameter(inches), slice count: \")\n",
+    "            args = args.split(',')\n",
+    "            radius = float(args[0].strip()) / 2\n",
+    "            slices = int(args[1].strip())\n",
+    "        except (ValueError, TypeError, IndexError) as e:\n",
+    "            print(\"Bad input & reason is:\", str(e))\n",
+    "            print(\"Type of exception:\", type(e))\n",
+    "            continue\n",
+    "\n",
+    "        # pizza analysis\n",
+    "        try:\n",
+    "            size = slice_size_v2(radius, slices)\n",
+    "            print('PIZZA: radius={}, slices={}, slice square inches={}'\n",
+    "                  .format(radius, slices, size))\n",
+    "        except (ZeroDivisionError, AssertionError) as e:\n",
+    "            print(\"Pizza analysis error!\", str(e))\n",
+    "            print(\"Type of exception:\", type(e))"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Try these problematic inputs for the main() function invocation\n",
+    "\n",
+    "- 10, -4: ArithmeticError (after we wrote assert statement)\n",
+    "- -10, 4: ArithmeticError (after we wrote assert statement)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 34,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Enter pizza diameter(inches), slice count: 20,0\n",
+      "Pizza analysis error! division by zero\n",
+      "Type of exception: <class 'ZeroDivisionError'>\n"
+     ]
+    },
+    {
+     "ename": "KeyboardInterrupt",
+     "evalue": "Interrupted by user",
+     "output_type": "error",
+     "traceback": [
+      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[0;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
+      "Cell \u001b[0;32mIn[34], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mmain_v6\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
+      "Cell \u001b[0;32mIn[33], line 14\u001b[0m, in \u001b[0;36mmain_v6\u001b[0;34m()\u001b[0m\n\u001b[1;32m     11\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(\u001b[38;5;241m5\u001b[39m):\n\u001b[1;32m     12\u001b[0m     \u001b[38;5;66;03m# grab input\u001b[39;00m\n\u001b[1;32m     13\u001b[0m     \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m---> 14\u001b[0m         args \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43minput\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mEnter pizza diameter(inches), slice count: \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m     15\u001b[0m         args \u001b[38;5;241m=\u001b[39m args\u001b[38;5;241m.\u001b[39msplit(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m,\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m     16\u001b[0m         radius \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mfloat\u001b[39m(args[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39mstrip()) \u001b[38;5;241m/\u001b[39m \u001b[38;5;241m2\u001b[39m\n",
+      "File \u001b[0;32m~/miniforge3/lib/python3.10/site-packages/ipykernel/kernelbase.py:1191\u001b[0m, in \u001b[0;36mKernel.raw_input\u001b[0;34m(self, prompt)\u001b[0m\n\u001b[1;32m   1189\u001b[0m     msg \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mraw_input was called, but this frontend does not support input requests.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m   1190\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m StdinNotImplementedError(msg)\n\u001b[0;32m-> 1191\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_input_request\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m   1192\u001b[0m \u001b[43m    \u001b[49m\u001b[38;5;28;43mstr\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mprompt\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m   1193\u001b[0m \u001b[43m    \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_parent_ident\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mshell\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m   1194\u001b[0m \u001b[43m    \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_parent\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mshell\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m   1195\u001b[0m \u001b[43m    \u001b[49m\u001b[43mpassword\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m   1196\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n",
+      "File \u001b[0;32m~/miniforge3/lib/python3.10/site-packages/ipykernel/kernelbase.py:1234\u001b[0m, in \u001b[0;36mKernel._input_request\u001b[0;34m(self, prompt, ident, parent, password)\u001b[0m\n\u001b[1;32m   1231\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m:\n\u001b[1;32m   1232\u001b[0m     \u001b[38;5;66;03m# re-raise KeyboardInterrupt, to truncate traceback\u001b[39;00m\n\u001b[1;32m   1233\u001b[0m     msg \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mInterrupted by user\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m-> 1234\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m(msg) \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m   1235\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m:\n\u001b[1;32m   1236\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlog\u001b[38;5;241m.\u001b[39mwarning(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mInvalid Message:\u001b[39m\u001b[38;5;124m\"\u001b[39m, exc_info\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\n",
+      "\u001b[0;31mKeyboardInterrupt\u001b[0m: Interrupted by user"
+     ]
+    }
+   ],
+   "source": [
+    "main_v6()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "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.10.6"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
-- 
GitLab