I've written a python log handler that I'm more than happy to share. The idea being that you can use the standard Python logging framework and also have the messages reflected back to ArcGIS through the arcpy
messages.
import logging
import logging.handlers
import arcpy
class ArcPyLogHandler(logging.handlers.RotatingFileHandler):
"""
Custom logging class that bounces messages to the arcpy tool window as well
as reflecting back to the file.
"""
def emit(self, record):
"""
Write the log message
"""
try:
msg = record.msg.format(record.args)
except:
msg = record.msg
if record.levelno >= logging.ERROR:
arcpy.AddError(msg)
elif record.levelno >= logging.WARNING:
arcpy.AddWarning(msg)
elif record.levelno >= logging.INFO:
arcpy.AddMessage(msg)
super(ArcPyLogHandler, self).emit(record)
You can then use the handler with a standard python logging object:
logger = logging.getLogger("LoggerName")
handler = ArcPyLogHandler(
"output_log.log",
maxBytes=1024 * 1024 * 2, #2MB log files
backupCount=10
)
formatter = logging.Formatter("%(levelname)-8s %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
And then you can write log messages like so:
logger.debug("A debug message")
logger.info("An info message")
logger.warning("A warning message")
logger.error("An error message")
logger.critical("A critical error message")
Which will write the messages of levels info and above through arcpy to the processing window, and all messages from debug and above to the log file specified with the format specified above (see the documentation for other formatting options).
Lastly you can use logger.exception
in an except
block which will give you a logging message at ERROR
level, and also dump the stacktrace to the log.
try:
#Something that might fail
except Exception as e:
logger.exception(e)