当前位置: 首页 > 知识库问答 >
问题:

python - 关于fastapi repeat_task定时任务修饰器与路由混搭使用日志写入错乱的问题?

车明贤
2023-10-31

我使用fastapi写了一个接口服务,服务内有路由api,也有定时任务,定时任务使用的是@repeat_task修饰器实现的,具体代码可以见

https://github.com/yuval9313/fastapi-restful/blob/master/fastapi_restful/tasks.py

我在使用的过程中遇到了一个问题,日志写入错乱,我需要将日志按照路由的名称\定时任务名称分别写入不同的文件,所以我封装了一个loguru

import sysfrom loguru import loggerimport osimport datetimeclass Logger_task:    def __init__(self, Log_dir):        self.logger = logger                # 清空所有设置        self.logger.remove()        self.Log_dir=os.path.dirname(os.path.abspath(__file__)) + '\\..\\logs\\{}\\'.format(Log_dir)        self.logger.add(sys.stdout,                        format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | "                               "<level>{level}</level>: "                                "<level>{message}</level>",                         )        file_name = '{}.log'.format(datetime.date.today())        global_log_file = os.path.join(self.Log_dir, file_name)        self.logger.add(global_log_file, level='DEBUG',                        format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | "                               "<level>{level}</level>: "                                "<level>{message}</level>",                          rotation="10 MB")    def get_task_logger(self):        return self.logger

定时任务\路由内调用

#定时任务调用@router.on_event('startup')@repeat_task(seconds=60, wait_first=True) #一分钟推送一次def repeat_task_push_FKD():    from Toollib.logger import Logger    logger_class = Logger(Log_dir='repeat_task_push_FKD')    task_logger=logger_class.get_task_logger()    task_logger.info("推送定时任务-开始")    push_FKD_class = push_FKD(logger=task_logger)    push_FKD_class.push_bill()    task_logger.info("推送定时任务-结束")#路由api调用class GetFile(BaseModel):    file_code: str    asr_code: str    file_format: str    file_name: str  @router.post("/GetFile")def GetFile(item: GetFile):    from Toollib.logger import Logger    logger_class = Logger(Log_dir='GetFile')    logger=logger_class.get_logger()    get_GetFile={"file_code":str(item.file_code),'asr_code':str(item.asr_code),'file_format':str(item.file_format),'file_name':str(item.file_name)}    logger.info("附件下载-收到获取文件参数:{}".format(str(get_GetFile)))    Get_File_class = Get_File(file_code=str(item.file_code),asr_code=str(item.asr_code),file_format=str(item.file_format),file_name=str(item.file_name),logger=logger)    Get_File_bases64 = Get_File_class.Get_bases_64()    #logger.remove()    if 'GetResult' in str(Get_File_bases64):        return respSuccessJson(data=Get_File_bases64['GetResult'], msg='获取成功')    else:        return Get_File_bases64

如上调用,当我的repeat_task_push_FKD()定时任务推送的时候,同时对方会调用我的路由/GetFile获取附件。此时定时任务repeat_task_push_FKD()内的后一半的日志会被写入到GetFile的日志文件内,这个是什么问题导致的?我应该怎么修改让它乖乖按照我设定的日志文件写入?
`

共有1个答案

麻茂材
2023-10-31

看起来,你在不同的任务中使用了不同的Logger实例,但没有正确地管理它们。在你的代码中,每次创建一个新的Logger实例时,你都会设置其日志级别、格式和输出位置,但你没有考虑到如果同时运行多个这样的实例,它们可能会互相干扰。

FastAPI框架在处理请求时通常会创建新的上下文,包括日志记录器。如果你在请求处理函数之外创建了日志记录器,那么FastAPI可能无法正确地将其与请求关联起来。

一个可能的解决方案是在每个请求处理函数中创建并使用日志记录器,而不是在整个应用上下文中共享它们。下面是如何做到这一点的一个例子:

from fastapi import FastAPIfrom loguru import loggerimport osimport datetimeapp = FastAPI()@app.on_event("startup")async def startup_event():    logger.add(os.path.dirname(os.path.abspath(__file__)) + "/logs/{}/repeat_task_push_FKD.log")    logger.add(os.path.dirname(os.path.abspath(__file__)) + "/logs/{}/GetFile.log".format(datetime.date.today()), rotation="10 MB")@app.post("/GetFile")async def GetFile(item: GetFile):    with logger.context():  # 创建一个上下文,这样我们就可以在请求结束时自动清理日志记录器        logger.info("附件下载-收到获取文件参数:{}".format(str(get_GetFile)))        Get_File_class = Get_File(file_code=str(item.file_code),asr_code=str(item.asr_code),file_format=str(item.file_format),file_name=str(item.file_name),logger=logger)        Get_File_bases64 = Get_File_class.Get_bases_64()        if 'GetResult' in str(Get_File_bases64):            return respSuccessJson(data=Get_File_bases64['GetResult'], msg='获取成功')        else:            return Get_File_bases64

在这个例子中,我使用了FastAPI的@app.on_event("startup")装饰器来初始化日志记录器,并在路由处理函数中使用with logger.context()上下文管理器来记录日志。这样,每个请求都有自己的日志记录器实例,它们不会互相干扰。

 类似资料:
  • 这个问题最好用一个示例日期来解释,例如datetime now(伦敦时间):21/08/2020 11:34 am 我对“ET”和UTC格式以及ISO格式的时间感到困惑,EDT和ET是一样的吗?为什么有这么多不同的格式,而且它们很混乱。有人能用一种简单的方式解释一下吗?除非我没有找到正确的文档,否则网上的信息不是很容易理解。 我希望将ET转换为UTC的原因是AWS cron作业仅采用此格式(如果我

  • 问题内容: 我正在寻找有关SQL Server日志文件的一些信息。我有一个大型数据库(2GB),最近由于任何原因都没有进行备份。数据库的日志文件增长到11GB左右,据我了解,这是数据库中发生的所有事务和语句。 我的问题: 是什么导致数据库日志文件被刷新?“冲洗”实际上是什么意思?在大型日志文件上执行文件压缩或数据库压缩有什么后果? 问题答案: 备份事务日志后,这些事务将从日志中被截断,但是该操作使

  • 我知道有很多关于这个的问题,但是我确实经历了所有的问题,并且有点困惑自己,我列出了我遵循的步骤,请让我知道我把它搞砸了。 1) 我只想在应用程序级别使用Log4j,所以需要复制WL_HOME/server/lib/wllog4j。jar和log4j。jar在Domail_Home/Lib? 2) 我使用的是Maven,我在pom中添加了Log4j依赖项。xml[war]。我把战争藏在耳朵里。 3)

  • 本文向大家介绍Python使用修饰器进行异常日志记录操作示例,包括了Python使用修饰器进行异常日志记录操作示例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Python使用修饰器进行异常日志记录操作。分享给大家供大家参考,具体如下: 当脚本中需要进行的的相同的异常操作很多的时候,可以用修饰器来简化代码。比如我需要记录抛出的异常: 在log_exception.py文件中, 在test

  • 在中有一个,可以将日志写入到。 我需要在中使用相同的功能,但我还没有找到这样做的选项。有人知道如何使用实现同样的效果吗?

  • 嗨,我有多项目分级设置 所有的工作都很好,但有一件事让我抓狂。在生成脚本中: 当我从命令行“gradlew”调用时<-默认任务将被执行 当我从命令行“gradlew tasks”<-task“All task runnable from root project”下调用时,我看到“build” 但当我尝试添加dependsOn('build')、dependsOn(':build')或depend