I have a minimal starlette app running via uvicorn doing nothing but returning a ping. Strangely, even with a single thread, I have 45 file handles to my log file. The handles increase with hits to the app and plateau at 45. I'm counting file handles using lsof:
lsof | grep kml-bkny.log
Of course, this is a minimal re-production. In actuality, my overall app is producing thousands of file handles. Some (~200) I would expect given threads*controller modules. However, I cant account for where thousands of file handles are being created. In my real program they dont plateau either, they grow forever.
here is my app (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)
I run this on the command line as such:
uvicorn api:app
I test the app using a simple script:
import time
import requests
while True:
time.sleep(1)
for _ in range(10):
r = requests.get(f'http://localhost:8000/kml/ping', timeout=5)
This is running on Ubuntu 18.04 with starlette==0.13.3 and uvicorn==0.11.3 on Python 3.6
As a comparison, there is no such effect when running w/o starlette+uvicorn. The below control program will produce 2 and only 2 file handles on lsof:
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")
Why would so many file handles be created that I see on lsof when introducing starlette and uvicorn?