{"id":"errors-try-except","slug":"try-except","title":"Catching errors with try and except","text":"An error that happens while a program runs is called an **exception**. Python *raises* the exception, and unless something *handles* it, the program stops and prints a traceback. A program can prepare for an exception with **`try`** and **`except`**:\n\n```python\ntry:\n    tickets = int(input(\"How many tickets? \"))\n    print(f\"Total: {tickets * 15} euros\")\nexcept ValueError:\n    print(\"That's not a whole number.\")\nprint(\"Thank you!\")\n```\n\n```input\ntwo\n```\n\n```output\nHow many tickets? two\nThat's not a whole number.\nThank you!\n```\n\nPython runs the `try` block. If a line in it raises a `ValueError`, the rest of the `try` block is skipped and the `except ValueError` block runs instead. After that the program carries on below the whole structure, as if nothing had happened. When no exception happens, the `except` block is skipped.\n\nThe `except` line names the kind of exception it handles. Any other kind still stops the program, which is good: an error you didn't expect should show up, not be hidden.\n\n### A fallback value\n\nSometimes the best reaction to bad input is a sensible default:\n\n```python\ntext = input(\"Font size: \")\ntry:\n    size = int(text)\nexcept ValueError:\n    size = 12\nprint(\"Using font size\", size)\n```\n\n```input\nbig\n```\n\n```output\nFont size: big\nUsing font size 12\n```\n\nKeep the `try` block small, with only the lines that can fail in the way you expect. Then it's clear what the `except` is for.\n\n### Asking until the input is good\n\nTogether with a loop, `try` and `except` can keep asking until the user types a number. In a function, `return` ends the loop as soon as the conversion succeeds:\n\n```python\ndef read_int(prompt):\n    while True:\n        try:\n            return int(input(prompt))\n        except ValueError:\n            print(\"Please type a whole number.\")\n\n\nyear = read_int(\"Year: \")\nprint(\"In ten years it will be\", year + 10)\n```\n\n```input\ntwenty\n20.5\n2030\n```\n\n```output\nYear: twenty\nPlease type a whole number.\nYear: 20.5\nPlease type a whole number.\nYear: 2030\nIn ten years it will be 2040\n```\n\n### Doing nothing with pass\n\nSometimes there's nothing to do about an exception except skip the bad value. An `except` block can't be empty, so it gets `pass`, the statement that does nothing:\n\n```python\ntotal = 0\nfor text in [\"5\", \"abc\", \"12\", \"\", \"3\"]:\n    try:\n        total += int(text)\n    except ValueError:\n        pass\nprint(total)\n```\n\n```output\n20\n```\n","task":"Fill in the blanks so the program prints the price with 24 % tax added, or `Not a price` when the input isn't a number. A run looks like this:\n\n```\nPrice: 10\nWith tax: 12.40\n```\n","kind":"fill","seed":"[[try]]:\n    price = float(input(\"Price: \"))\n    print(f\"With tax: {price * 1.24:.2f}\")\n[[except]] ValueError:\n    print(\"Not a price\")\n","solution":"try:\n    price = float(input(\"Price: \"))\n    print(f\"With tax: {price * 1.24:.2f}\")\nexcept ValueError:\n    print(\"Not a price\")\n","hints":["The block that might fail starts with one keyword, and the block that handles the failure with another.","They are `try` and `except`."],"tests":[{"name":"Test 1","stdin":"10\n","expect":"Price: 10\nWith tax: 12.40","hidden":false},{"name":"Test 2","stdin":"ten\n","expect":"Price: ten\nNot a price","hidden":true},{"name":"Test 3","stdin":"2.5\n","expect":"Price: 2.5\nWith tax: 3.10","hidden":true}],"require":[],"forbid":[],"more":[{"task":"In many countries a decimal number is written with a comma, like `72,5`, but `float` only accepts a point. Write a function `read_decimal(prompt)` that asks for a number with the given prompt until the user types one, and returns it as a `float`. It accepts both `72.5` and `72,5`. After anything that isn't a number, it prints `Not a number, try again` and asks again.\n\nWith this main program\n\n```python\nweight = read_decimal(\"Weight in kg: \")\nprint(weight)\n```\n\na run looks like this:\n\n```\nWeight in kg: heavy\nNot a number, try again\nWeight in kg: 72,5\n72.5\n```\n","kind":"code","seed":"def read_decimal(prompt):\n    pass\n\n\nif __name__ == \"__main__\":\n    weight = read_decimal(\"Weight in kg: \")\n    print(weight)\n","solution":"def read_decimal(prompt):\n    while True:\n        text = input(prompt)\n        try:\n            return float(text.replace(\",\", \".\"))\n        except ValueError:\n            print(\"Not a number, try again\")\n\n\nif __name__ == \"__main__\":\n    weight = read_decimal(\"Weight in kg: \")\n    print(weight)\n","hints":["Use a `while True:` loop with `input(prompt)` inside it, and try to convert the text in a `try` block.","Before converting, swap a comma for a point: `text.replace(\",\", \".\")`.","`return` the converted number inside the `try` block. In the `except ValueError:` block, print the message, and the loop asks again."],"tests":[{"name":"print(read_decimal(\"Weight in kg: \"))","stdin":"heavy\n72,5\n","call":"print(read_decimal(\"Weight in kg: \"))\n","expect":"Weight in kg: heavy\nNot a number, try again\nWeight in kg: 72,5\n72.5","hidden":false},{"name":"read_decimal(\"Height: \")","stdin":"1.8.2\ntall\n1.82\n","call":"read_decimal(\"Height: \")\n","expect":"Height: 1.8.2\nNot a number, try again\nHeight: tall\nNot a number, try again\nHeight: 1.82\n1.82","hidden":true,"returns":true},{"name":"read_decimal(\"Price: \")","stdin":"3\n","call":"read_decimal(\"Price: \")\n","expect":"Price: 3\n3.0","hidden":true,"returns":true}],"require":[],"forbid":[]},{"task":"Write a program that adds up whole numbers the user types, until the user types `done`. Anything that isn't a whole number is skipped with the message `Skipped: ` and the text. At the end the program prints the sum.\n\nA run looks like this:\n\n```\nNumber: 4\nNumber: four\nSkipped: four\nNumber: 10\nNumber: done\nSum: 14\n```\n","kind":"code","seed":"total = 0\n","solution":"total = 0\nwhile True:\n    text = input(\"Number: \")\n    if text == \"done\":\n        break\n    try:\n        total += int(text)\n    except ValueError:\n        print(\"Skipped:\", text)\nprint(\"Sum:\", total)\n","hints":["Read the input in a `while True:` loop and `break` when the text is `done`.","Convert and add inside a `try` block. A `ValueError` means the text wasn't a whole number.","In the `except ValueError:` block, print `Skipped:` and the text. Print the sum after the loop."],"tests":[{"name":"Test 1","stdin":"4\nfour\n10\ndone\n","expect":"Number: 4\nNumber: four\nSkipped: four\nNumber: 10\nNumber: done\nSum: 14","hidden":false},{"name":"Test 2","stdin":"-3\n2.5\n8\nx\ndone\n","expect":"Number: -3\nNumber: 2.5\nSkipped: 2.5\nNumber: 8\nNumber: x\nSkipped: x\nNumber: done\nSum: 5","hidden":true},{"name":"Test 3","stdin":"done\n","expect":"Number: done\nSum: 0","hidden":true}],"require":[],"forbid":[]}]}