这是我获取打印到控制台和文件的记录器的方法:
import logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
handler.setFormatter(formatter)
handler2 = logging.FileHandler(os.path.join(os.path.split(os.path.abspath(__file__))[0], 'my.log'), mode='w')
handler2.setFormatter(formatter)
logger.addHandler(handler)
logger.addHandler(handler2)
有没有办法在更少的操作中完成类似的操作?我并不特别关心文件模式或文件名。
编辑:这个用例就是我正在为一个新脚本进行原型设计,并且不希望花时间编写配置文件直到以后。
答案 0 :(得分:1)
我的观点:当你进行原型设计时,你需要一个每个模块的日志文件。
为此,您可以按照以下步骤进行处理:
LogNameFileHandler
:这是logging.StreamHandler
的子类,其行为类似logging.FileHandler
,但会为每个记录器创建一个日志文件(基于其名称)。LOGGER
,它使用此处理程序和经典控制台记录器(按照您的建议方式)设置(根)记录器。logger = LOGGER.getChild(__name__)
。在log_handler.py
:
import io
import logging
import os
class LogNameFileHandler(logging.StreamHandler):
def __init__(self, root_dir, mode='a', encoding=None):
super(LogNameFileHandler, self).__init__(stream=None)
self.root_dir = os.path.abspath(root_dir)
self.mode = mode
self.encoding = encoding
# Set stream to None, because StreamHandler set it to sys.stderr
self.stream = None
#: :type log_path: str
self.log_path = None
def _open(self):
log_dir = os.path.dirname(self.log_path)
if not os.path.isdir(log_dir):
os.makedirs(log_dir)
return io.open(self.log_path, mode=self.mode, encoding=self.encoding)
def close(self):
self.acquire()
try:
try:
if self.stream:
try:
self.flush()
finally:
stream = self.stream
self.stream = None
if hasattr(stream, "close"):
stream.close()
finally:
super(LogNameFileHandler, self).close()
finally:
self.release()
def emit(self, record):
name = record.name.replace(".", os.sep)
log_name = name + ".log"
self.log_path = os.path.join(self.root_dir, log_name)
self.stream = self._open()
super(LogNameFileHandler, self).emit(record)
此处理程序为每个emit
打开一个新文件,当然,由您来处理缓存...对于原型设计,它应该没问题。您可以使用映射record.name
=> stream
。
在log_setup.py
:
import logging
import os
from log_handler import LogNameFileHandler
def _init_logger(log_dir, name=None):
logger = logging.getLogger(name)
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter(u'%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
handler1 = logging.StreamHandler()
handler1.setFormatter(formatter)
handler2 = LogNameFileHandler(log_dir, mode="a+", encoding="utf8")
handler2.setFormatter(formatter)
logger.addHandler(handler1)
logger.addHandler(handler2)
return logger
LOGGER = _init_logger(os.path.dirname(__file__))
这个模块定义了LOGGER
单例,您可以在所有Python模块中使用它...
在package/module.py
:
from log_setup import LOGGER
logger = LOGGER.getChild(__name__)
logger.info("hello solution3")
这就是全部(所有灰尘都在地毯下)。
如果你设置了root
记录器,你可以写:
import logging
logger = logging.getLogger(__name__)
...
答案 1 :(得分:0)
我很好奇:你为什么要这样?
您可以在INI文件中使用外部配置,并使用logging.config.fileConfig
加载它。
或者
创建自己的句柄,组合文件和控制台处理程序。
或者
创建一个类文件对象,将其写入文件并在控制台中。然后将此文件与logging.basicConfig
一起使用。