-
Notifications
You must be signed in to change notification settings - Fork 125
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move exception handling and logging to new guide
- Loading branch information
1 parent
4cbd5e9
commit aafb4e6
Showing
2 changed files
with
234 additions
and
299 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,234 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Exception Handling and Logging \n", | ||
"\n", | ||
"Exception handling and logging are two important components of programming, in particular for debugging purposes. Detailed technical guides are available online (e.g., [Loggin](https://docs.python.org/3/howto/logging.html), [Error and Exceptions](https://docs.python.org/3/tutorial/errors.html)). Here we only repeat a few key points and list a few guidelines for CLIMADA." | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"### Exception handling" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"#### CLIMADA guidelines" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"1. Catch specific exceptions if possible, i.e, if not needed do not catch all exceptions.\n", | ||
"\n", | ||
"2. Do not catch exception if you do not handle them. \n", | ||
"\n", | ||
"3. Make a clear explanatory message when you raise an error (similarly to when you use the logger to inform the user). Think of future users and how it helps them understanding the error and debugging their code.\n", | ||
"\n", | ||
"4. Catch an exception when it arises.\n", | ||
"\n", | ||
"5. When you can an exception and raise an error, it is in often (but not always) a good habit to not throw away the first caught exception as it may contain useful information for debugging. (use `raise Error from`)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"#Bad (1)\n", | ||
"x = 1\n", | ||
"try:\n", | ||
" l = len(events)\n", | ||
" if l < 1:\n", | ||
" print(\"l is too short\")\n", | ||
"except:\n", | ||
" pass" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"#Still bad (2)\n", | ||
"try:\n", | ||
" l = len(events)\n", | ||
" if l < 1:\n", | ||
" print(\"l is too short\")\n", | ||
"except TypeError:\n", | ||
" pass" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"#Better, but still unsufficient (3)\n", | ||
"try:\n", | ||
" l = len(events)\n", | ||
" if l < 1:\n", | ||
" raise ValueError(\"To compute an impact there must be at least one event.\")\n", | ||
"except TypeError:\n", | ||
" raise TypeError(\"The provided variable events is not a list\")" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"#Even better (4)\n", | ||
"try:\n", | ||
" l = len(events)\n", | ||
"except TypeError:\n", | ||
" raise TypeError(\"The provided variable events is not a list\")\n", | ||
"if l < 1:\n", | ||
" raise ValueError(\"To compute an impact there must be at least one event.\")" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"#Even better (5)\n", | ||
"try:\n", | ||
" l = len(events)\n", | ||
"except TypeError as tper:\n", | ||
" raise TypeError(\"The provided variable events is not a list\") from tper\n", | ||
"if l < 1:\n", | ||
" raise ValueError(\"To compute an impact there must be at least one event.\")\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"#### Exceptions reminder" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Why do we bother to handle exceptions? \n", | ||
"\n", | ||
"- The most essential benefit is to inform the user of the error, while still allowing the program to proceed. " | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"### Logging" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"#### CLIMADA guidelines" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"- In CLIMADA, you cannot use printing. Any output must go into the LOGGER. \n", | ||
"\n", | ||
"\n", | ||
"- For any logging messages, always think about the audience. What would a user or developer need for information? This also implies to carefully think about the correct LOGGER level. For instance, some information is for debugging, then use the debug level. In this case, make sure that the message actually helps the debugging process! Some message might just to inform the user about certain default parameters, then use the inform level. See below for more details about logger levels.\n", | ||
"\n", | ||
"\n", | ||
"- Do not overuse the LOGGER. Think about which level of logging. Logging errors must be useful for debugging." | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"You can set the level of the LOGGER using `climada.util.config.LOGGER.setLevel(logging.XXX)`. This way you can for instance 'turn-off' info messages when you are making an application. For example, setting the logger to the \"ERROR\" level, use:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"import logging\n", | ||
"from climada.util.config import LOGGER\n", | ||
"LOGGER.setLevel(logging.ERROR)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"What levels to use in CLIMADA?\n", | ||
"\n", | ||
"- Debug: what you would print while developing/debugging \n", | ||
"\n", | ||
"\n", | ||
"- Info: information for example in the check instance\n", | ||
"\n", | ||
"\n", | ||
"- Warning: whenever CLIMADA fills in values, makes an extrapolation, computes something that might potentially lead to unwanted results (e.g., the 250year damages extrapolated from data over 20 years)\n", | ||
"\n", | ||
"No known use case:\n", | ||
"\n", | ||
"- Error: instead, raise an Error and add the message (raise ValueError(\"Error message\"))\n", | ||
"\n", | ||
"\n", | ||
"- Critical: ..." | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"#### Reminder about Logging " | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"\"Logging is a means of tracking events that happen when some software runs.\" \n", | ||
"\n", | ||
"*When to use logging*\n", | ||
"\n", | ||
"\"Logging provides a set of convenience functions for simple logging usage. These are debug(), info(), warning(), error() and critical(). To determine when to use logging, see the table below, which states, for each of a set of common tasks, the best tool to use for it.\"\n", | ||
"\n", | ||
"<img src=\"./img/WhenToLog.png\" alt=\"Doc\" width=\"600\">\n", | ||
"\n", | ||
"*Logger level*\n", | ||
"\n", | ||
"\"The logging functions are named after the level or severity of the events they are used to track. The standard levels and their applicability are described below (in increasing order of severity):\"\n", | ||
"\n", | ||
"<img src=\"./img/LoggerLevels.png\" alt=\"Doc\" width=\"600\">" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"language_info": { | ||
"name": "python" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |
Oops, something went wrong.