Solved 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! :+1:

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