我已经阅读了一些关于此的帖子,但我仍然感到困惑。我有这个日志记录设置:
import logging
class MongoHandler(logging.Handler):
def __init__(self):
logging.Handler.__init__(self)
from pymongo import Connection
self.db = Connection('db_server').db_name
def emit(self, record):
try:
self.db.Logging.save(record.__dict__)
except:
print 'Logging Error: Unable to save log entry to db'
mh = MongoHandler()
sh = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(threadName)s - %(levelname)s - %(message)s')
sh.setFormatter(formatter)
log = logging.getLogger('DeviceMonitor_%s' % hostname)
log.addHandler(mh)
log.addHandler(sh)
log.setLevel(logging.INFO)
我希望能够为StreamHandler和MongoHandler设置不同的级别。这可能吗?还是我需要第二个Logger obj?
答案 0 :(得分:68)
您可以为每个日志记录处理程序设置不同的日志记录级别,但似乎您必须将记录器的级别设置为“最低”。在下面的示例中,我将记录器设置为DEBUG,将流处理程序设置为INFO,将TimedRotatingFileHandler设置为DEBUG。因此该文件具有DEBUG条目,并且流仅输出INFO。您不能仅将DEBUG指向一个且仅将INFO指向另一个处理程序。为此你需要另一个记录器。
logger = logging.getLogger("mylog")
formatter = logging.Formatter('%(asctime)s | %(name)s | %(levelname)s: %(message)s')
logger.setLevel(logging.DEBUG)
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.INFO)
stream_handler.setFormatter(formatter)
logFilePath = "my.log"
file_handler = logging.handlers.TimedRotatingFileHandler(filename = logFilePath, when = 'midnight', backupCount = 30)
file_handler.setFormatter(formatter)
file_handler.setLevel(logging.DEBUG)
logger.addHandler(file_handler)
logger.addHandler(stream_handler)
logger.info("Started");
try:
x = 14
y = 0
z = x / y
except Exception as ex:
logger.error("Operation failed.")
logger.debug("Encountered {0} when trying to perform calculation.".format(ex))
logger.info("Ended");
答案 1 :(得分:4)
GrantVS答案的补充:
我必须使用
logging.basicConfig(level=logging.DEBUG)
为了它的工作。否则很好的答案,谢谢!
马里奥
PS:由于某些原因,系统不允许我直接评论GrantVS的答案。
答案 2 :(得分:3)
我需要一点时间来理解这一点
答案 3 :(得分:0)
有同样的问题,但是该解决方案不适用于iPython,因为QtConsole会自动创建一个没有设置级别的处理程序:
import logging
root = logging.getLogger()
root.handlers
Out: [<StreamHandler <stderr> (NOTSET)>]
因此,尽管我的文件处理程序和流处理程序具有不同的级别,但iPython仍将DEBUG和INFO都打印到控制台。
此主题为我指出了这个问题:Logging module does not print in IPython
我制作了一个名为custom_logging.py的帮助程序模块(此堆栈线程对此有很大帮助!),以使在其他模块中记录日志更加方便:
import logging
from pathlib import Path
import sys
def _add_stream_handler(logger: logging.Logger):
stream_handler = logging.StreamHandler()
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
stream_handler.setFormatter(formatter)
stream_handler.setLevel(logging.INFO)
logger.addHandler(stream_handler)
return logger
def _add_file_handler(logger: logging.Logger, log_path: Path):
file_handler = logging.FileHandler(log_path, mode='w')
formatter = logging.Formatter(
fmt='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', datefmt='%m-%d %H:%M')
file_handler.setFormatter(formatter)
file_handler.setLevel(logging.DEBUG)
logger.addHandler(file_handler)
return logger
def create_logger(root_dir: Path, caller: str) -> logging.Logger:
log_path = root_dir / 'logs' / f'{caller}.log'
logger = logging.getLogger(caller)
root = logging.getLogger()
logger.setLevel(logging.DEBUG)
# If haven't already launched handlers...
if not len(logger.handlers):
_add_file_handler(logger=logger, log_path=log_path)
_add_stream_handler(logger=logger)
logger.info('Logging started.')
# Delete the Qtconsole stderr handler
# ... as it automatically logs both DEBUG & INFO to stderr
if root.handlers:
root.handlers = []
return logger
def log_dataframe(df, logger: logging.Logger, name: str = "DataFrame") -> None:
logger.debug(
f'''{name} head:\n {df.head()}\n----------\n''')
def log_dataframes(*args, logger: logging.Logger) -> None:
for gdf in args:
logger.debug(
f'''DataFrame head:\n {gdf.head()}\n----------\n''')
可以通过以下方式使用其功能:
from custom_logging import create_logger, log_dataframe
或者import custom_logging
和custom_logging.create_logger()
等
另请参见官方日志记录手册中的“多个处理程序和格式化程序”和“记录到多个目标”部分: https://docs.python.org/3/howto/logging-cookbook.html#logging-cookbook