Logging in Cinema 4D



  • Hello,
    I'm trying to implement a logger for my plugin that saves logging messages from level DEBUG & higher. When I try using Python's logging module's basicConfig method, I'm unable to change the level or write the file. Here's the test script I'm using:

    import c4d, os, logging
    from c4d import storage
    
    def main():
        WRITEPATH = os.path.join(storage.GeGetC4DPath(c4d.C4D_PATH_DESKTOP), "MyLog.log")
        logging.basicConfig(filename=WRITEPATH, level=logging.DEBUG, filemode='w', format='%(name)s - %(levelname)s - %(message)s')
        logging.debug('This is a debug message')
        logging.info('This is an info message')
        logging.warning('This is a warning message')
        logging.error('This is an error message')
        logging.critical('This is a critical message')
    
    if __name__=='__main__':
        main()
    

    I've tried finding more information on Cinema 4D's logging and found this document on the LoggerInterface. I couldn't, however, find an example of how this is to be used. Can someone please provide a working example of saving log messages to a file in Cinema 4D? Thank you!



  • Hi @blastframe,

    I'm using it currently more or less like this:

    The StreamHandler will print the result to the Python-Console and the FileHandler will write to disk. However, I'm also keen to know how to create my own LoggerInterface via Python. A simple example on this would be really appreciated.

    import c4d
    import os
    import logging
    
    def get_logger():
        plugin_name = "YourAwesomePlugin"
    
        #Logger for printing to Python-Console
        formatter1 = logging.Formatter('YourAwesomePlugin: [%(asctime)s] : %(module)s[%(lineno)s] : [%(levelname)s] "%(message)s"')
        handler = logging.StreamHandler()
        handler.setFormatter(formatter1)
        logger = logging.Logger(plugin_name)
        logger.addHandler(handler)
    
        #Logger for *.log file
        formatter2 = logging.Formatter('[%(asctime)s] : %(module)s[%(lineno)s] : [%(levelname)s] "%(message)s"')
        logpath = os.path.join(c4d.storage.GeGetC4DPath(c4d.C4D_PATH_DESKTOP), "MyLog.log")
        filehandler = logging.FileHandler(logpath)
        filehandler.setFormatter(formatter2)
        logger.addHandler(filehandler)
    
        return logger
    
    def main():
        logger = get_logger()
        
        logger.debug('This is a debug message')
        logger.info('This is an info message')
        logger.warning('This is a warning message')
        logger.error('This is an error message')
        logger.critical('This is a critical message')
    
    if __name__=='__main__':
        main()
    

    Cheers,
    Lasse



  • Hi @blastframe,

    I'm using it currently more or less like this:

    The StreamHandler will print the result to the Python-Console and the FileHandler will write to disk. However, I'm also keen to know how to create my own LoggerInterface via Python. A simple example on this would be really appreciated.

    import c4d
    import os
    import logging
    
    def get_logger():
        plugin_name = "YourAwesomePlugin"
    
        #Logger for printing to Python-Console
        formatter1 = logging.Formatter('YourAwesomePlugin: [%(asctime)s] : %(module)s[%(lineno)s] : [%(levelname)s] "%(message)s"')
        handler = logging.StreamHandler()
        handler.setFormatter(formatter1)
        logger = logging.Logger(plugin_name)
        logger.addHandler(handler)
    
        #Logger for *.log file
        formatter2 = logging.Formatter('[%(asctime)s] : %(module)s[%(lineno)s] : [%(levelname)s] "%(message)s"')
        logpath = os.path.join(c4d.storage.GeGetC4DPath(c4d.C4D_PATH_DESKTOP), "MyLog.log")
        filehandler = logging.FileHandler(logpath)
        filehandler.setFormatter(formatter2)
        logger.addHandler(filehandler)
    
        return logger
    
    def main():
        logger = get_logger()
        
        logger.debug('This is a debug message')
        logger.info('This is an info message')
        logger.warning('This is a warning message')
        logger.error('This is an error message')
        logger.critical('This is a critical message')
    
    if __name__=='__main__':
        main()
    

    Cheers,
    Lasse



  • @lasselauch Absolutely awesome, thank you Lasse! This was just what I needed! 👍



  • Hi @blastframe unfortunately for the moment is not possible to implement its own logger in python.

    However, you could use any existing loggers.

    Here an example that writes into the Application (Default) Logger.

    import maxon
    
    txt = "My Wonderfull Text"
    defaultLogger = maxon.Loggers.Default()
    defaultLogger.Write(maxon.TARGETAUDIENCE.ALL, txt, maxon.MAXON_SOURCE_LOCATION(1), maxon.WRITEMETA.DEFAULT)
    

    Note that the print simply reroutes to the Python logger. But it can be useful to directly use the logger to write if you pass the write meta maxon.WRITEMETA.UI_SYNC_DRAW this way you can force a redraw of the console (slower) after each print, this can be used to avoid the limitation mentioned in the second part of this post.

    Cheers,
    Maxime


Log in to reply