我一直在尝试使用Python内置的logging库创建一个数据库处理程序。我尝试通过子类化主日志模块的“Handler
”类来实现,但它会抛出许多错误,而StreamHandler
类是完全正常的,并且它的编写方式与我的DatabaseHandler
类相同。
我已经检查了logging库的文档,但似乎没有用于创建自定义日志处理程序的类。因此,我决定编写DatabaseHandler
类,而不继承Handler
类的属性,并且当我输入第一行以创建'logs'
表(如果不存在)时,SQLite 3代码会抛出错误,说没有这样的表。
我的代码:
from logging import getLogger, StreamHandler, Formatter, Handler, NOTSET, getLevelName
from datetime import datetime as date_time
from sqlite3 import connect
class DatabaseHandler(Handler):
def __init__(self, db_file):
super().__init__(self)
self.db_file = db_file
self.db_file = connect(self.db_file)
def emit(self, record):
"""
Conditionally emit the specified logging record.
Emission depends on filters which may have been added to the handler.
Wrap the actual emission of the record with acquisition/release of
the I/O thread lock. Returns whether the filter passed the record for
emission.
"""
self.db_file.executescript(
'CREATE TABLE IF NOT EXISTS logs (date TEXT, '
'time TEXT, lvl INTEGER, lvl_name TEXT, msg TEXT, '
'logger TEXT, lineno INTEGER);'
'INSERT INTO logs VALUES ("%s", "%s", %s, "%s", "%s", "%s", %s)' % (
date_time.now().strftime('%A, the %d of %B, %Y'),
date_time.now().strftime('%I:%M %p'),
record.levelno,
record.level,
record.msg,
record.name,
record.lineno
)
)
self.db_file.commit()
self.db_file.close()
logger = getLogger(__name__)
logger_formatter = Formatter(
fmt = '<LVL: %(levelno)s (%(levelname)s), LOGGER: %(name)s> - "%(message)s at %(asctime)s"',
datefmt = '%I:%M %p on %A, the %d of %B, %Y'
)
logger_stream_handler = StreamHandler()
logger_stream_handler.setFormatter(logger_formatter)
logger_stream_handler.setLevel(10)
logger_database_handler = DatabaseHandler('test.db')
logger.addHandler(logger_stream_handler)
logger.addHandler(logger_database_handler)
logger.log(
msg = 'Something happened',
level = 10
)
print(connect('test.db').execute('SELECT name FROM sqlite_master WHERE type = "table"').fetchall())
它的工作原理是将其添加为日志记录器的处理程序,每次记录某些内容并创建一个LogRecord时,它也会将LogRecord的详细信息存储在数据库的logs表中。我还为该类创建了一个“emit”方法,因为我认为logging __init__.py模块文件中的Handler类在进行新的日志调用并创建LogRecord时会触发该方法。但是,问题在于:每当我在类的__init__方法上调用super().__init__(self)以继承来自Handler类的属性时,它就会抛出此异常。
Traceback (most recent call last):
File "<string>", line 47, in <module>
File "<string>", line 7, in _init_
File"/lib/python3.8/logging/_init_.py", line 865, in _init_
self.level = checkLevel(level)
File "/lib/python3.8/logging/__init_.py", line 192, in checkLevel
elif str(level) == level:
File "/lib/python3.8/logging/__init_.py", line 1035, in _repr_
level = getLevelName(self.level)
AttributeError: 'DatabaseHandler' object has no attribute 'level'
[Program finished]
[Program finished]
Handler
是创建自定义处理程序的正确方法。你遇到了什么错误?此外,你绝对应该调用super.__init__
,否则你的处理程序甚至都没有level
属性。 - undefinedAttributeError: 'DatabaseHandler' object has no attribute 'level'
。此外,我为该类创建了一个emit
方法,因为我在 logging 的__init__.py
模块文件中看到了Handler
类有这个方法,我认为这个方法在创建新的日志调用和LogRecord
时被调用。 - undefinedHandler
类的init方法有这行代码:self.level = _checkLevel(level)
实现emit
确实是正确的做法。 - undefined追踪回溯(最近的调用在最后): 文件 "",第47行,在中
文件 "",第7行,在__init__中
文件 "/lib/python3.8/logging/__init__.py",第865行,在__init__中
self.level = _checkLevel(level)
文件 "/lib/python3.8/logging/__init__.py",第192行,在_checkLevel中
elif str(level) == level:
文件 "/lib/python3.8/logging/__init__.py",第1035行,在__repr__中
level = getLevelName(self.level)
AttributeError: 'DatabaseHandler'对象没有属性'level'
[程序已结束]
- undefinedself
传递给super().__init__()
。看看堆栈跟踪!super
初始化程序正在尝试将您的参数(即您的DatabaseHandler
实例)转换为级别字符串,而处理程序的__repr__
方法正在尝试访问尚不存在的level
属性... - undefined