Python Windows 服务仅在作为 -debug 启动时运行

python windows service only runs when started as -debug

提问人:Tekay37 提问时间:11/9/2023 最后编辑:Tekay37 更新时间:11/9/2023 访问量:40

问:

我有一个运行 hypercorn 的 Windows 服务。在 python 3.7 中一切正常。现在我们想将我们的服务移动到 python 3.11,但是在启动服务时出现错误:

Traceback (most recent call last):
  File "...\service.py", line 108, in main
    run_hypercorn(app, self.host, self.port, self.shutdown_trigger)
  File "...\run.py", line 36, in run_hypercorn
    asyncio.run(serve(dispatcher, hypercorn_cfg, shutdown_trigger=shutdown_trigger.wait))
  File "asyncio\runners.py", line 189, in run
  File "asyncio\runners.py", line 59, in __enter__
  File "asyncio\runners.py", line 137, in _lazy_init
  File "asyncio\events.py", line 806, in new_event_loop
  File "asyncio\events.py", line 695, in new_event_loop
  File "asyncio\windows_events.py", line 315, in __init__
  File "asyncio\proactor_events.py", line 642, in __init__
ValueError: set_wakeup_fd only works in main thread of the main interpreter

但是,这仅在通过 启动服务时发生,当我通过 启动它时不会发生。在后一种情况下,服务运行没有问题。sc start service_namepytonservice.exe -debug service_name

失败的代码如下所示:

import asyncio
from hypercorn.config import Config as HypercornConfig
from hypercorn.asyncio import serve
from hypercorn.middleware import DispatcherMiddleware

def run_hypercorn(app, host, port, shutdown_trigger=None):
    dav = dav_app(...)

    dispatcher = DispatcherMiddleware(
        {
            '/dav': dav,
            '': app,
        }
    )

    hypercorn_cfg = HypercornConfig()
    hypercorn_cfg.bind = f'{host}:{port}'
    if shutdown_trigger is None:
        asyncio.run(serve(dispatcher, hypercorn_cfg))
    else:
        loop = asyncio.get_event_loop()  # fails here
        loop.run_until_complete(serve(dispatcher, hypercorn_cfg, shutdown_trigger=shutdown_trigger.wait))

我读到对 asyncio 进行了一些更改,包括 ,这导致了一些错误,但据称这些错误已在 3.9 中修复。get_event_loop()

然而。我也尝试用

asyncio.run(serve(dispatcher, hypercorn_cfg, shutdown_trigger=shutdown_trigger.wait))

但是,我收到同样的错误。当我完全省略shutdown_trigger时,同样的问题。

服务等级没什么特别的:

class AppServerSvc(win32serviceutil.ServiceFramework):
    _svc_name_ = ""
    _svc_display_name_ = ""

    def __init__(self, args):
        self.shutdown_trigger = asyncio.Event()
        self.app: FastAPI = None
        self.config: Config = None
        self.port: int = None
        self.host: str = None

    def SvcDoRun(self, *args, **kwargs):
        self.ReportServiceStatus(win32service.SERVICE_START_PENDING)
        self.main()

    def main():
        from ___.app import app
        from ___.run import run_hypercorn, run_uvicorn

        self.config = Config.new('config.ini', installation_folder=self.path)
        self.app = app

        self.port = self.config.webserver.get('port', None)
        self.host = self.config.webserver.get('host', None)

        self.app.state.config = self.config

        self.ReportServiceStatus(win32service.SERVICE_RUNNING)
    
        run_hypercorn(app, self.host, self.port, self.shutdown_trigger)

if __name__ == '__main__':
    win32serviceutil.HandleCommandLine(AppServerSvc)

我不明白如何定期运行服务将代码放在不同的线程中,我不知道该怎么做(或者在这种情况下如何以不同的方式启动 hypercorn)。

编辑

我还检查了我所在的线程:在这两种情况下都有 5 个线程,当前线程是 .MainThread

这是否表明 python 中仍然存在错误?

蟒蛇 python-asyncio python-3.11 hypercorn

评论


答:

1赞 Tekay37 11/9/2023 #1

没关系。我找到了解决方案。出于某种原因,默认值不喜欢作为服务运行。WindowsProactorEventLoopPolicy

添加

asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

解决了问题。如果有人能向我解释,为什么会这样,那就太好了。

祝你有美好的一天,亲爱的 StackOverflowers。🌻