'python logging does not release file till all program finish

I am working on python logging and I came across this problem. I could not release the file unless I stopped the python code.

Basically, I'd like to accomplish that writing a line of log data then releasing the file then opening the file again and appending new log data.

Can anyone shed some light on that how can I do that?

Cheers!

if __name__ == '__main__':
    # Main logger
    main_logger = logging.getLogger()
    main_logger.setLevel(logging.INFO)
    file_handlerWrite = RotatingFileHandler('{}'.format(pth), mode='w')
    old_factory = logging.getLogRecordFactory()
    isThisFirstTime = True

    if isThisFirstTime:
        add_logformatter(file_handlerWrite, log_title_format, logging.WARNING)
        logging.getLogger().warning(
            'Num;        Logging Time;                   MotorFreq;      MotorSpeed;     PWMVal;')
        print("write:")
        try:
            file_handlerWrite.acquire()
            file_handlerWrite.flush()
            file_handlerWrite.close()
        except (OSError, ValueError):
            pass
        finally:
            file_handlerWrite.release()
            main_logger.removeHandler(file_handlerWrite)
    else:
            pass
    logging.shutdown()

    file_handlerAppend = RotatingFileHandler('{}'.format(pth), mode='a', backupCount=1)

    add_logformatter(file_handlerAppend, log_data_format, logging.INFO)
    print("appers")
    for x in range(100):
        mtrFreq = random.randint(4000, 5000)
        mtSod = random.randint(4000, 5000)
        pwm = random.randint(4000, 5000)

        logging.setLogRecordFactory(record_factory_factory(x))

        logging.getLogger().info("    %d;          %d;            %d;" % (mtrFreq, mtSod, pwm))
    print("doneeee")
    try:
        file_handlerAppend.acquire()
        file_handlerAppend.flush()
        file_handlerAppend.close()
    except (OSError, ValueError):
        pass
    finally:
        file_handlerAppend.release()
        main_logger.removeHandler(file_handlerAppend)

    logging.shutdown()
    print("shottdown")
    while(1):
        pass


Solution 1:[1]

You would need to write your own Handler class, I'd imagine.

Basing on the default FileHandler and StreamHandler, maybe something like this.

filename_getter must be a function that returns the filename for a given log record; it can of course just be a function that always returns the same thing, if you don't need rotation or anything...

import logging
import time
from logging import StreamHandler


class QuickReleaseFileHandler(StreamHandler):
    def __init__(self, filename_getter):
        super().__init__()
        self.stream = None
        self.filename_getter = filename_getter

    def setStream(self, stream):
        raise NotImplementedError("You can't call setStream on this handler")

    def flush(self) -> None:
        pass  # we don't need to flush, since we close the stream after every message

    def emit(self, record) -> None:
        with open(self.filename_getter(record), 'a') as self.stream:
            super().emit(record)
        self.stream = None


fh = QuickReleaseFileHandler(
    lambda _: f'foo_{int(time.time() // 2)}.log',
)

logging.basicConfig(level=logging.INFO, handlers=[fh])

for x in range(10):
    print(x)
    logging.info(f"Hello {x}")
    time.sleep(1)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 AKX