How it works...
To properly capture any unexpected exceptions, the main function should be wrapped into a try-except block, as done in Step 4 in the How to do it… section. Compare this to how Step 1 is not wrapping the code:
try:
main(...)
except Exception as exc:
# Something went wrong
logging.exception("Error running task")
exit(1)
Note that logging the exception is important for getting information on what went wrong.
The extra step to exit with status 1 with the exit(1) call informs the operating system that something went wrong with our script.
The logging module allows us to log. Note the basic configuration, which includes an optional file to store the logs, the format, and the level of the logs to display.
Creating logs is easy. You can do this by making a call to the method logging.<logging level>, (where logging level is debug, info, and so on). For example:
>>> import logging
>>> logging.basicConfig(level=logging.INFO)
>>> logging.warning('a warning message')
WARNING:root:a warning message
>>> logging.info('an info message')
INFO:root:an info message
>>> logging.debug('a debug message')
>>>
Note how logs with a severity lower than INFO are not displayed. Use the level definition to tweak how much information to display. This may change, for example, how DEBUG logs may be used only while developing the task, but not be displayed when running it. Notice that task_with_error_handling_step4.py is defining the logging level to be DEBUG, by default.
logging.exception() is a special case that will create an ERROR log, but it will also include information about the exception, such as the stack trace.
Remember to check logs to discover errors. A useful reminder is to add a note on the results file, like this:
try:
main(args.n1, args.n2, args.output)
except Exception as exc:
logging.exception(exc)
print('There has been an error. Check the logs', file=args.output)