[FEATURE] Make event-handling optional
See original GitHub issueI’m trying to get Uvicorn to run as a Windows service so event logging and automatic start/restart can be handled more cleanly than by just running uvicorn
as a scheduled task. I’ve run into a number of roadblocks, though most of these I’ve been able to work my way around with some configuration. The main roadbloack I still have is event-loop compatibility. Due to some odd behavior of Python threads while running as a windows service (see mhammond/pywin32#1452), it’s not currently possible for Python code to register signal handlers. That makes the default ProactorEventLoop
unusable, but that can be solved by falling back to a SelectorEventLoop
, which used to be the default event loop for Windows before Python 3.8. Not being able to handle the signal for Ctrl+C is not too much of a problem for my use case either, since I can just set the service to trip the Server#should_exit
flag manually when the service is asked to stop.
So with all this said and done, if you ignore the service boilerplate wrapping my code, I’m essentially running Uvicorn like this:
import asyncio
import logging
from logging.handlers import NTEventLogHandler
from uvicorn import Server, Config
from app import app
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
windows_log_handler = NTEventLogHandler('myASGIApp')
logging.getLogger().addHandler(windows_log_handler)
server_config = Config(
app, host="0.0.0.0", port=8000,
# Can't log to stdout as a service
log_config={"version": 1},
# Don't let uvicorn select what loop to use
loop="asyncio",
)
self.app_server = Server(server_config)
self.app_server.run()
The main problem I still have with this is this line, which will try to setup event handlers even though doing so will immediately fail given my event loop configuration:
https://github.com/encode/uvicorn/blob/996aa2d459360f61507caa142b89a8f5b562cb6d/uvicorn/main.py#L360
I currently have to go and comment out that line in the uvicorn module code to get my application to start at all, which is less than ideal. Would it be possible to make signal handling optional if uvicorn is running from inside a Python script, maybe?
EDIT: I would have tried import uvicorn; uvicorn.main.HANDLED_SIGNALS = ()
, but it turns out that uvicorn.main:main
is imported by uvicorn
in a way that shadows the real uvicorn.main
package, so even this awful hack is not an option.
Issue Analytics
- State:
- Created 4 years ago
- Comments:5 (2 by maintainers)
Top GitHub Comments
Yeah, pretty much. Subclassing
uvicorn.Server
also seems like a much better workaround than what I had. (Why didn’t I think of that?)This should be fixed by https://github.com/encode/uvicorn/pull/871 without the need to subclass