[英]Running uvicorn as WindowsService, signal only works in main thread
在 Windows 服務中啟動 uvicorn 應用程序時,該服務無法啟動,錯誤指示信號只能在主線程中處理。
這是事件日志中捕獲的錯誤消息:
Traceback (most recent call last):
File "site-packages\win32\lib\win32serviceutil.py", line 839, in SvcRun
File "WindowsService.py", line 49, in SvcDoRun
File "site-packages\uvicorn\main.py", line 279, in run
File "site-packages\uvicorn\main.py", line 307, in run
File "asyncio\base_events.py", line 584, in run_until_complete
File "site-packages\uvicorn\main.py", line 319, in serve
File "site-packages\uvicorn\main.py", line 459, in install_signal_handlers
File "signal.py", line 47, in signal
ValueError: signal only works in main thread
該項目在 fin un 調試模式下工作。
.\dist\WindowsService.exe debug
沒有參數允許我指定不處理信號。
以下是我如何以編程方式啟動 uvicorn 應用程序:
uvicorn.run(app.main,
host=config['server']['host'],
port=config['server']['port'],
log_level=config['server']['loglevel'],
reload=False)
該應用程序使用win32serviceutil.ServiceFramework編譯為凍結的可執行文件
pyinstaller -F --hidden-import=win32timezone --additional-hooks-dir pyinstaller-hooks WindowsService.py
我希望啟動 Windows 服務並運行 uvicorn 應用程序。
我找到了一個解決方案,這意味着有一個由 Windows 服務調用的控制台應用程序。 在我的控制台應用程序中,我有機會在主線程上工作並根據要求啟動 uvicorn。
子進程調用由:
def SvcDoRun(self):
_log('has started')
# determine if application is a script file or frozen exe
if getattr(sys, 'frozen', False):
application_path = os.path.dirname(sys.executable)
elif __file__:
application_path = os.path.dirname(__file__)
exe_name = os.path.join(application_path, self._app_exe_name_)
_log('launchin subprocess for {exe_name}'.format(exe_name=exe_name))
p = subprocess.Popen([exe_name])
_log('is running in subprocess id {process_id}'.format(process_id=p.pid))
while True:
result = win32event.WaitForSingleObject(self._stop_event, 5000)
if result == win32event.WAIT_OBJECT_0:
# stop requested
_log('is stopping')
p.kill()
break
_log('has stopped')
我有同樣的問題,不喜歡你運行子進程的解決方案。 我發現https://github.com/encode/uvicorn/issues/526解釋了這個問題。 我的解決方法:
config = uvicorn.Config(app, ...)
server = uvicorn.Server(config=config)
# According to https://github.com/encode/uvicorn/issues/526, on Python 3.8+ you MIGHT also need:
# asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
# But in my case it didn't seem to be necessary
server.install_signal_handlers = lambda: None # this is the necessary workaround
server.run()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.