In the logging howto documentation there is this example:
# create logger
logger = logging.getLogger('simple_example')
# create console handler and set level to debug
ch = logging.StreamHandler()
# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# add formatter to ch
# add ch to logger
It's there for fine-tuning (you can have multiple handlers, and each could have different levels set) — you can safely not set level on the handler, which will cause it to process all messages (a.k.a. NOTSET level), and leave level filtering to the logger.
Logger is also the first to filter the message based on a level — if you set the logger to INFO, and all handlers to DEBUG, you still won't receive DEBUG messages on handlers — they'll be rejected by the logger itself. If you set logger to DEBUG, but all handlers to INFO, you won't receive any DEBUG messages either — because while the logger says "ok, process this", the handlers reject it (DEBUG < INFO).