I am trying to build a logger logger_script.py for my python scripts that:
- outputs a log file with customizable log level.
 - outputs a console output with customizable log level (not necessarily equal to the log file's one)
 - logs unhandled exceptions both to the log file and to the console
 
I achieved the first two points by following the answer to "https://stackoverflow.com/questions/29087297/is-there-a-way-to-change-the-filemode-for-a-logger-object-that-is-not-configured/29087645 ". I adapted it a to my needs and it now looks like:
import sys
import logging
def create_logger(log_filename, logfile_level, console_level):
    # create logger and file handler
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.DEBUG)
    fh = logging.FileHandler(log_filename, mode='w')
    fh.setLevel(logfile_level)
    # create console handler with independent log level
    ch = logging.StreamHandler(stream=sys.stdout)
    ch.setLevel(console_level)
    formatter = logging.Formatter('[%(asctime)s] %(levelname)8s: %(message)s' +
                                  ' (%(filename)s:%(lineno)s)',
                                  datefmt='%m-%d, %H:%M:%S')
    fh.setFormatter(formatter)
    ch.setFormatter(formatter)
    if (logger.hasHandlers()): #clear pre-existing logs (?)
        logger.handlers.clear() 
        
    logger.addHandler(ch)
    logger.addHandler(fh)
    
    return logger
#create the logger: file log + console output
logger = create_logger("LogFile.log", logging.INFO, logging.WARNING)
#####  piece of code with handled exceptions:  #####
beta = 3
while beta > -3:
    try:
        2/beta
        logger.info("division successful".rjust(20))
    except ZeroDivisionError:
        logger.exception("ZeroDivisionError".rjust(20))    
    beta -= 1
##### piece of code with unhandled exception  ##### 
gamma = 1/0
    
However, when running a code with an unhandled exception (see last line), these do not get passed to the log file, only to the console.
I followed advices from Logging uncaught exceptions in Python and added the following snippet;
def handle_exception(exc_type, exc_value, exc_traceback):
    if issubclass(exc_type, KeyboardInterrupt):
        sys.__excepthook__(exc_type, exc_value, exc_traceback)
        return
    logger.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback))
sys.excepthook = handle_exception
either before or after the logger creation lines, but it does not work in my case.
How can I make unhandled exception appear, together with their traceback message?
I would like to avoid encapsulating the whole code into a try:    except statement.