A traceback reads from the bottom up. The last line names the error and says what went wrong. The frames above it show the chain of calls that led there, oldest first; the lowest frame in your own code is usually where to look.
print is fine while exploring, but scripts that run every day should log. logging lets you tag each message with a level and decide later which levels to keep:
DEBUG for details, INFO for normal progress, WARNING for something odd that didn't stop the run, ERROR for a failure.
logger.setLevel(logging.WARNING) keeps warnings and errors and drops the rest.
- Inside
except, logger.exception("...") records the error and its traceback.
Good log messages say which record: "row C-104: blank amount, skipped" is useful at 2 a.m.; "error" is not.
In these exercises, a setup cell collects the import logger's messages in log_lines as "LEVEL message", so you can see what was logged.