Reputation: 2153
I have a cronjob running a python script which I added a logging
to, but since it's a daily job it is really annoying that I get daily emails of it's function, but I can't seem to find a setting, that will make it log only into the logfile.
#!/usr/bin/python
import logging, logging.handlers
LOGFILENAME = "log.log"
logging.basicConfig()
log = logging.getLogger("nameoflog")
log.setLevel(logging.DEBUG)
handler = logging.handlers.WatchedFileHandler(LOGFILENAME)
handler.setLevel(logging.DEBUG)
handler.setFormatter(logging.Formatter("%(asctime)-15s %(levelname)-8s %(name)s %(message)s"))
log.addHandler(handler)
log.info("something happening")
How is it possible to make logging
only write to a file and not to file and STDOUT
?
Upvotes: 10
Views: 17140
Reputation: 81
Logging in Python can be complex, and the default logging module has some limitations esp because stream handler is attached to the root logger. It doesn't provide a straightforward way to log messages exclusively to a file without logging them to the console. The FileLogger class presented here extends the built-in logging functionality to overcome this limitation, allowing you to log messages to both a file and the console, or exclusively to a file if desired.
class FileLogger(logging.Logger):
def __init__(self, name, filename, mode='a', level=logging.INFO, fformatter=None, log_to_console=False, sformatter=None):
super().__init__(name, level)
# Create a custom file handler
self.file_handler = logging.FileHandler(filename=filename, mode=mode)
# Set the formatter for the file handler
if fformatter is not None:
self.file_handler.setFormatter(fformatter)
# Add the file handler to the logger
self.addHandler(self.file_handler)
if log_to_console:
# Create a console handler
self.console_handler = logging.StreamHandler() # Prints to the console
# Set the formatter for the console handler
if not sformatter:
sformatter = fformatter
self.console_handler.setFormatter(sformatter)
# Add the console handler to the logger
self.addHandler(self.console_handler)
def fdebug(self, msg, pre_msg=''):
if pre_msg:
print(pre_msg)
self.debug(msg)
def finfo(self, msg):
self.info(msg)
def fwarn(self, msg):
self.warning(msg)
def ferror(self, msg):
self.error(msg)
def fcritical(self, msg):
self.critical(msg)
# Test the logging
if __name__ == '__main__':
s_log_level = logging.CRITICAL
file_log_level = logging.WARN
log_format = "[%(asctime)s.%(msecs)03d] %(message)s"
log_fp = f'tmp.log'
logging.basicConfig(format=log_format, level=s_log_level, datefmt="%H:%M:%S")
# Create an instance of the custom logger
formatter = logging.Formatter(log_format, "%H:%M:%S")
fLogger = FileLogger(__name__, log_fp, mode='a', level=file_log_level, fformatter=formatter)
fLogger.fdebug("This will be logged to file with DEBUG level")
fLogger.finfo("This will be logged to file with INFO level")
fLogger.fwarn("This will be logged to file with WARNING level")
fLogger.ferror("This will be logged to file with ERROR level")
fLogger.fcritical("This will be logged to file with CRITICAL level")
logging.debug("This Debug will be logged to console")
logging.info("This info will be logged to console")
logging.warning("This warning also be logged to console")
logging.critical("This critical also be logged to console")
In this solution, the FileLogger class extends the logging.Logger class and provides the ability to log messages exclusively to a file. The constructor of the FileLogger class accepts parameters for the log file name (filename) and mode (mode), allowing customization of the log file behavior.
To use this solution, simply create an instance of the FileLogger class and call the logging methods (info, debug, warning, etc.) on the logger instance. The log messages will be written only to the specified log file.
Remember to adjust the filename parameter to set the desired log file name, and you can change the mode parameter to control the behavior of the log file (e.g., 'a' for append, 'w' for overwrite).
Upvotes: 1
Reputation: 77347
The problem is that you call logging.basicConfig()
which sets up logging to stdout
. basicConfig
is just a helper method used when you don't want to make more detailed logging calls. Since you setup the methods yourself, you should not call basicConfig
.
Upvotes: 9
Reputation: 3056
Here's an example that works for me (it does not print the message to stdout, but only to example.log
):
def logToFile():
import logging
logging.basicConfig(filename='example.log',level=logging.DEBUG)
logging.info("trying to log to file")
logToFile()
Upvotes: 3