使用Starlette和Uvicorn进行Python日志记录时,文件句柄过多(在lsof上)

2024-05-26 17:42:56 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个最小的Starlete应用程序通过uvicorn运行,除了返回ping之外什么也不做。奇怪的是,即使只有一个线程,我的日志文件也有45个文件句柄。随着应用程序点击量的增加,句柄会增加,并在45时达到稳定。我正在使用lsof计算文件句柄:

lsof | grep kml-bkny.log

当然,这是一个最小的再生产。实际上,我的整个应用程序正在生成数千个文件句柄。一些(~200)我希望给定线程*控制器模块。但是,我无法解释创建数千个文件句柄的位置。在我真正的项目中,它们也不会停滞,它们会永远成长

这是我的应用程序(api.py):

import logging

from starlette.applications import Starlette
from starlette.responses import JSONResponse

logger = logging.getLogger("kml")
logger.setLevel(logging.DEBUG)
handler = logging.FileHandler('/tmp/kml-bkny.log')
logger.addHandler(handler)

def controller_ping(request):
    try:
        logger.debug("Received /ping request")
        return JSONResponse({}, status_code=200)
    except Exception as e:
        logger.error(e)
        return JSONResponse({}, status_code=500)

app = Starlette()
app.add_route(path='/kml/ping', methods=['GET'], route=controller_ping)

我在命令行上运行此命令,如下所示:

uvicorn api:app

我使用一个简单的脚本测试应用程序:

import time
import requests

while True:
    time.sleep(1)
    for _ in range(10):
        r = requests.get(f'http://localhost:8000/kml/ping', timeout=5)

这在Ubuntu 18.04上运行,在Python 3.6上starlette==0.13.3和uvicorn==0.11.3

作为比较,在不使用starlette+uvicorn的情况下运行时没有这种效果。以下控制程序将在lsof上生成2个且仅2个文件句柄:

import logging
import time

logger = logging.getLogger("kml")
logger.setLevel(logging.DEBUG)
handler = logging.FileHandler('/tmp/kml-bkny.log')
logger.addHandler(handler)

while True:
    time.sleep(1)
    for _ in range(10):
        logger.debug("Received /ping request")

为什么在引入starlette和uvicorn时会创建如此多的文件句柄


Tags: 文件importlog应用程序timeloggingloggerkml

热门问题