我正在使用 pywin32 创建 Windows 服务。
问题是每当我调用
asyncio
、asyncio.run()
、asyncio.ensure_future()
或asyncio.get_event_loop()
等asyncio.ProactorEventLoop()
函数时,我都会得到一个ValueError: set_wakeup_fd only works in main thread
。
Python版本:3.8.8
执行为:
python test.py install
,然后python test.py start
。发现错误在C:/xxx/errorLogs2.txt
代码:
import socket
import win32serviceutil
import servicemanager
import win32event
import win32service
import asyncio
class Test(win32serviceutil.ServiceFramework):
_svc_name_ = 'testService'
_svc_display_name_ = 'Test Service'
_svc_description_ = 'Test Service Description'
@classmethod
def parse_command_line(cls):
win32serviceutil.HandleCommandLine(cls)
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
socket.setdefaulttimeout(60)
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
def SvcDoRun(self):
try:
l = asyncio.get_event_loop() # Fails here
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_, ''))
except Exception as e:
with open('C:/xxx/errorLogs2.txt', 'a') as f:
f.write(str(e) + '\n')
if __name__ == '__main__':
Test.parse_command_line()
我在尝试连接到 Azure 事件中心(在后台使用 asyncio)的服务时遇到了同样的问题。每次进程尝试连接到事件中心时都会失败并显示
ValueError: set_wakeup_fd only works in main thread
。
我向服务添加了一些日志记录,以确保它不会尝试从不同的线程启动连接,但日志都表明该服务正在运行
MainThread
。
在偶然发现this页面后,我终于找到了解决方案。
我将这一行添加到我的代码中,一切都开始按预期工作。
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
虽然我不完全理解为什么这个解决方案有效,但我相信它与默认策略
WindowsProactorEventLoopPolicy
使用I/O完成端口有关,这可能会导致问题。
我也不确定为什么使用默认事件循环策略在使用
python -m serviceName debug
运行服务时有效,但在使用 python -m serviceName start
运行服务时不起作用。