gpt4 book ai didi

python - 将 SqlAlchemy 记录到数据库

转载 作者:太空宇宙 更新时间:2023-11-04 04:20:28 25 4
gpt4 key购买 nike

我正在编写一个小型应用程序,它应该使用 sqlalchemy 将所有内容记录到数据库中。受此启发:

python logging to database

还有这个:

https://docs.pylonsproject.org/projects/pyramid-cookbook/en/latest/logging/sqlalchemy_logger.html我想出了一个解决方案,除了 sqlalchemy (!) 本身生成的日志消息之外,它适用于所有相关库的所有日志消息。

这是一个最小的例子,重现了我的问题:

import logging
import datetime
from sqlalchemy import Column, DateTime, String, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

Base = declarative_base()


# define table
class TblLog(Base):
__tablename__ = 'Tbl_Log'

LOG_TIME = Column(DateTime, primary_key=True)
LOG_NAME = Column(String(100))
LOG_LEVEL = Column(String(100))
LOG_MSG = Column(String(2000))

def __init__(self, time, name, lvl, msg):
self.LOG_TIME = time
self.LOG_NAME = name
self.LOG_LEVEL = lvl
self.LOG_MSG = msg

# custom log handler that emits to the database
class DatabaseHandler(logging.Handler):

def __init__(self, session):
super().__init__()
self.session = session
self.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
self.setLevel(logging.DEBUG)

def emit(self, record):

self.format(record)

log_time = datetime.datetime.strptime(record.__dict__['asctime'], "%Y-%m-%d %H:%M:%S,%f")

log_record = TblLog(log_time, record.__dict__['name'], record.__dict__['levelname'], record.__dict__['message'])

self.session.add(log_record)
self.session.commit()

启用 sqlalchemy (!) 日志进行测试:

if __name__ == '__main__':
# simple logging config
logging.basicConfig(
format='%(asctime)s : %(name)s : %(levelname)s : %(message)s',
level=logging.DEBUG,
)
logger_sqlalchemy = logging.getLogger('sqlalchemy')
logger_sqlalchemy.setLevel(logging.INFO)


# test with sqlite in memory database
DB_STRING = 'sqlite:///:memory:'
engine = create_engine(DB_STRING, echo=False)
Base.metadata.create_all(engine)
Session = sessionmaker()
session = Session(bind=engine)

# adding custom handler:
logger_sqlalchemy.addHandler(DatabaseHandler(session))

logger_sqlalchemy.info('this is a test message')

这提高了

AttributeError: 'NoneType' object has no attribute 'set'

如有必要,我可以粘贴整个回溯。我怀疑问题出现了因为 TblLog(...) 调用会产生日志记录,因此处理程序会向自身发出记录?!

这个问题的最佳解决方案是什么,即我可以在处理程序中使用 sqlalchemy 将 sqlalchemy 日志消息写入数据库吗?

我有点卡在这里,感谢您的帮助...

最佳答案

I suspect that the issue arises because the TblLog(...) call produces a log record and thus the handler emits records to itself?!

这不是紧迫的问题。失败的原因是 SQLAlchemy 在配置映射器时发出日志消息,其中第一个消息是在 TblLog 的映射器完全配置之前发送的,因此,您的错误。

如果您将 StreamHandler 添加到您的 logger_sqlalchemy 实例之前 DatabaseHandler 您将能够看到日志消息 logger_sqlalchemy 正在接收直至崩溃。使它绊倒的日志消息是 (TblLog|Tbl_Log) _post_configure_properties() started,它来自 _post_configure_properties()方法。该方法的文档字符串包括:

This is a deferred configuration step which is intended to execute once all mappers have been constructed.

这表明 TblLog 的映射器配置尚未完成。

如果您然后从记录器中删除 DatabaseHandler 并只保留 StreamHandler 您将看到该方法继续执行的操作(我还删除了您的 basicConfig() 为清楚起见:

(TblLog|Tbl_Log) _post_configure_properties() started
# this is where your code crashed originally
(TblLog|Tbl_Log) initialize prop LOG_TIME
(TblLog|Tbl_Log) initialize prop LOG_NAME
(TblLog|Tbl_Log) initialize prop LOG_LEVEL
(TblLog|Tbl_Log) initialize prop LOG_MSG
(TblLog|Tbl_Log) _post_configure_properties() complete

如您所见,列描述符的一些初始化似乎是在发出第一条日志消息后发生的。这就是您收到错误的原因,当您尝试使用 ORM 时,ORM 尚未准备好。

您可以实例化一个虚拟的 TblLog 实例以强制映射器在添加处理程序之前进行配置,例如:

# ensure TblLog mapper configured
TblLog(time=None, name=None, lvl=None, msg=None)
logger_sqlalchemy.addHandler(DatabaseHandler(session))
logger_sqlalchemy.info('this is a test message')

但是您随后会遇到一个新问题:SQLAlchemy 在整个刷新/提交过程中发出日志。因此,当第一条日志消息被刷新到数据库时,它会生成一条新的日志消息,该消息本身会生成一条新的日志消息等等......无限递归。

所以我的回答是:

What would be the best solution for this problem, i.e. can I write sqlalchemy log messages to a database using sqlalchemy in the handler??

如果您还 try catch sqlalchemy 日志记录,那么答案是否定的。

一些可能的解决方案:

  • 不要使用 SQLAlchemy 将日志消息写入数据库。假设您在应用程序的其他部分使用 SQLAlchemy,请直接使用 dpapi 客户端将日志写入数据库,并且明确不要将客户端的日志消息写入数据库(否​​则您将遇到相同的递归问题) .
  • 使用 HTTPHandler 将您的日志消息发送到网络服务它将日志消息写入数据库。
  • 让 sqlalchemy 记录到文件中,而其他所有内容都记录到数据库中。您甚至可以设置一个 cron 作业,以在单独的进程中定期将文件中的 sqlalchemy 日志写入数据库。
  • Logging as a service

关于python - 将 SqlAlchemy 记录到数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54581554/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com