Below are 2 different modules: driver module and employee module. I am
trying the log the debug statements in two different files but write now the
log file is getting created with no debug statements in it.
I tried all the way.
Driver file
import logging
logger = logging.getLogger(__name__)
formatter = logging.Formatter("%(asctime)s : %(levelname)s : %(name)s : %
(message)s")
file_handler = logging.FileHandler('driver.log')
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
#logging.basicConfig(filename="Employee.log", level=logging.DEBUG,
format="%(asctime)s : %(levelname)s : %(name)s : %(message)s")
from Employee import Employee
logger.debug("Before creation of object")
Emp1= Employee("Rahul",1,100000)
logger.debug("After creation of object")
Emp1.display()
#Employee Module
import logging
logger = logging.getLogger(__name__)
formatter = logging.Formatter("%(asctime)s : %(levelname)s : %(name)s : %
(message)s")
file_handler = logging.FileHandler("Employee.log")
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
#logging.basicConfig(filename="Employee.log", level=logging.DEBUG,
format="%(asctime)s : %(levelname)s : %(name)s : %(message)s")
class Employee():
def __init__(self,name,id,salary):
self.salary = salary
self.name=name
self.id =id
def increment(self, per):
self.salary=self.salary*((100+per)/100)
def decrement(self, per):
self.salary=self.salary*((100-per)/100)
def display(self):
logger.debug("Name is {}".format(self.name))
logger.debug("ID is {}".format(self.id))
logger.debug("Sal is {}".format(self.salary))
You need to set the level on the logger instance as well. The handlers and the logger each have a level. A logger can have multiple handlers assigned to it, each logging at a different level.
logger.setLevel(logging.DEBUG)
Edit: https://docs.python.org/3/library/logging.html#logging.Logger.setLevel
Related
I am trying to learn about logging. My code is logging the information that I want but it's duplicating the message.
The first code block below is at the top of my py file.
import logging
import traceback
# setup the file name
log_file_name = dt.date.today().strftime('%Y_%B_%d')
log_path = "C:/some_path/"
# setup the logging
log_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
logger = logging.getLogger(__name__)
logger.setLevel('DEBUG')
file_handler = logging.FileHandler(log_path + log_file_name + '.log')
formatter = logging.Formatter(log_format)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
In my function I'm using the line like below to log some information.
logger.debug('some message')
My py file doesn't import any other modules which have any logging information so I'm a bit confused as to why the messages are being duplicated?
logging.py
import logging
def log():
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s:%(name)s:%(message)s')
file_handler = logging.FileHandler('sample.log')
file_handler.setLevel(logging.ERROR)
file_handler.setFormatter(formatter)
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(formatter)
logger.addHandler(file_handler)
logger.addHandler(stream_handler)
return logger
I have this above piece of code. i want to call this function in every file in the project for logs and to print on command line by streamhandler and store log it in the same sample.log file across a project.
Hello Stack Overflow users,
i'm writing a simple code and i got a "AttributeError" exception
log_level = 'INFO' # DEBUG - INFO - WARNING - ERROR - CRITICAL
logging.basicConfig(
format=('%(asctime)s > [%(levelname)s] in %(funcName)s on line '
'%(lineno)d > %(message)s'), level = logging.log_level, \
filename='logs.log', filemode='w', encoding='utf-8')
Sorry for asking a suck stupid question.
Thank you in advance.
Not very clear on your requirement, but the below approach can be a neat solution
def get_logger(cls, logger_name, create_file=False):
# create logger
log = logging.getLogger(logger_name)
log.setLevel(level=logging.INFO)
# create formatter and add it to the handlers
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
if create_file:
# create file handler for logger.
fh = logging.FileHandler('my_log.log')
fh.setLevel(level=logging.DEBUG)
fh.setFormatter(formatter)
# reate console handler for logger.
ch = logging.StreamHandler()
ch.setLevel(level=logging.DEBUG)
ch.setFormatter(formatter)
# add handlers to logger.
if create_file:
log.addHandler(fh)
log.addHandler(ch)
return log
I try to use two different loggers to handle different log levels. For example, I want info message store in a file and don't log error message. Error messages of some special functions will email to the user.
I write a simple program to test the logging module.
Code:
import logging
def_logger = logging.getLogger("debuglogger")
def_logger.setLevel(logging.DEBUG)
maillogger = logging.getLogger("mail")
maillogger.setLevel(logging.ERROR)
mailhandler = logging.StreamHandler()
mailhandler.setLevel(logging.ERROR)
mailhandler.setFormatter(logging.Formatter('Error: %(asctime)s - %(name)s - %(levelname)s - %(message)s'))
maillogger.addHandler(mailhandler)
print(def_logger.getEffectiveLevel())
print(maillogger.getEffectiveLevel())
def_logger.info("info 1")
maillogger.info("info 2")
def_logger.error("error 1")
maillogger.error("error 2")
Output:
Output result
I can see the level of them is correct, but both of them act like the level is ERROR.
How can I correctly configure them?
Answer: Base on blues advice, I added a handler and it solved my problem.
Here is the modified code:
import logging
def_logger = logging.getLogger("debuglogger")
def_logger.setLevel(logging.DEBUG)
def_logger.addHandler(logging.StreamHandler()) #added a handler here
maillogger = logging.getLogger("mail")
maillogger.setLevel(logging.ERROR)
mailhandler = logging.StreamHandler()
mailhandler.setLevel(logging.ERROR)
mailhandler.setFormatter(logging.Formatter('Error: %(asctime)s - %(name)s - %(levelname)s - %(message)s'))
maillogger.addHandler(mailhandler)
print(def_logger.getEffectiveLevel())
print(maillogger.getEffectiveLevel())
def_logger.info("info 1")
maillogger.info("info 2")
def_logger.error("error 1")
maillogger.error("error 2")
Neither the def_logger nor any of its parents have a handler attached to it. So what happens is that the logging module falls back to logging.lastResort which by default is a StreamHandler with level Warning. That is the reason why the info message doesn't appear, while the error does. So to solve your problem attach a handler to the def_logger.
Note: In your scenario the only parent both loggers have is the default root handler.
You could add a filter for each logger or handler to process only records of interest
import logging
def filter_info(record):
return True if record.levelno == logging.INFO else False
def filter_error(record):
return True if record.levelno >= logging.ERROR else False
# define debug logger
def_logger = logging.getLogger("debuglogger")
def_logger.setLevel(logging.DEBUG)
def_logger.addFilter(filter_info) # add filter directly to this logger since you didn't define any handler
# define handler for mail logger
mail_handler = logging.StreamHandler()
mail_handler.setLevel(logging.ERROR)
mail_handler.setFormatter(logging.Formatter('Error: %(asctime)s - %(name)s - %(levelname)s - %(message)s'))
mail_handler.addFilter(filter_error) # add filter to handler
mail_logger = logging.getLogger("mail")
mail_logger.setLevel(logging.ERROR)
mail_logger.addHandler(mail_handler)
# test
def_logger.info("info 1")
mail_logger.info("info 2")
def_logger.error("error 1")
mail_logger.error("error 2")
If filter return True, the log record is processed. Otherwise, it is skipped.
Note:
Filter attached to a logger won't be called for log record that is generated by descendant loggers. For example, if you add a filter to logger A, it won't be called for records that are generated by logger A.B nor A.B.C.
Filter attached to a handler is consulted before an event is emitted by that handler.
This means that you just need one logger and add two handlers with different filters attached.
import logging
def filter_info(record):
return True if record.levelno == logging.INFO else False
def filter_error(record):
return True if record.levelno >= logging.ERROR else False
# define your logger
logger = logging.getLogger("myapp")
logger.setLevel(logging.DEBUG)
# define handler for file
file_handler = logging.FileHandler('path_to_log.txt')
file_handler.level = logging.INFO
file_handler.addFilter(filter_info) # add filter to handler
# define handler for mail
mail_handler = logging.StreamHandler()
mail_handler.setLevel(logging.ERROR)
mail_handler.setFormatter(logging.Formatter('Error: %(asctime)s - %(name)s - %(levelname)s - %(message)s'))
mail_handler.addFilter(filter_error) # add filter to handler
logger.addHandler(file_handler)
logger.addHandler(mail_handler)
# test
logger.info("info 1")
logger.info("info 2")
logger.error("error 1")
logger.error("error 2")
I am trying to log all exceptions within my application. I want to have different handlers, one handler to log all information to a file and only critical problems to my email.
I created a file_handler, which should log everything and email_handler for the critical problems. The handlers work, apart from catching unexpected errors. I tried to log everything with the root logger, which has the same configuration as the file_handler, which works. Why doesn't my file_handler catch unexpected errors?
Here is my code:
# root logger
logging.basicConfig(filename='flask.log', level=logging.WARNING)
# own logger
logger = logging.getLogger('flask')
file_handler = logging.handlers.TimedRotatingFileHandler('flask.log', when='D', interval=1)
email_handler = SMTPHandler(...)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger.setLevel(logging.DEBUG)
file_handler.setLevel(logging.DEBUG)
email_handler.setLevel(logging.WARNING)
file_handler.setFormatter(formatter)
email_handler.setFormatter(formatter)
logger.addHandler(file_handler)
logger.addHandler(email_handler)
If I have an error in a function (example Class A doesn't has attribute X), the unexpected problem only gets logged by the root logger.
Workaround:
If I don't give "my" logger a name, I get the root logger. My handlers then take his information and distribute them. It is not ideal, because it should work with "my" logger as well.
Workaround code:
# own logger
logger = logging.getLogger() # no name -> logger = root logger
file_handler = logging.handlers.TimedRotatingFileHandler('flask.log', when='D', interval=1)
email_handler = SMTPHandler(...)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger.setLevel(logging.DEBUG)
file_handler.setLevel(logging.DEBUG)
email_handler.setLevel(logging.WARNING)
file_handler.setFormatter(formatter)
email_handler.setFormatter(formatter)
logger.addHandler(file_handler)
logger.addHandler(email_handler)