我发现了使用似乎有效的子线程的解决方案。不太确定这是否可能会带来意想不到的后果。
-
更新:
我相信下面的更新版本“将SystemExit注入”女服务员线程就可以了。我认为您的原始版本会严重杀死线程,但是此消息会打印“线程已完成”,表示正常关闭。
欢迎更正或改进!
import ctypesimport osimport randomimport socketimport threadingfrom flask import Flask, escape, requestimport servicemanagerimport win32eventimport win32serviceimport win32serviceutilfrom waitress import serveapp = Flask(__name__)# waitress thread exit based on:# https://www.geeksforgeeks.org/python-different-ways-to-kill-a-thread/@app.route('/')def hello(): random.seed() x = random.randint(1, 1000000) name = request.args.get("name", "World") return 'Hello, %s! - %s - %s' % (escape(name), x, os.getpid())class ServerThread(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): print('thread startn') serve(app, listen='*:5000') # blocking print('thread donen') def get_id(self): # returns id of the respective thread if hasattr(self, '_thread_id'): return self._thread_id for id, thread in threading._active.items(): if thread is self: return id def exit(self): thread_id = self.get_id() res = ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, ctypes.py_object(SystemExit)) if res > 1: ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, 0) print('Exception raise failure')class SMWinservice(win32serviceutil.Serviceframework): _svc_name_ = 'WaitressService' _svc_display_name_ = 'Waitress server' _svc_description_ = 'Python waitress WSGI service' @classmethod def parse_command_line(cls): win32serviceutil.HandleCommandLine(cls) def __init__(self, args): win32serviceutil.Serviceframework.__init__(self, args) self.stopEvt = win32event.CreateEvent(None, 0, 0, None) socket.setdefaulttimeout(60) def SvcStop(self): servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE, servicemanager.PYS_SERVICE_STOPPED, (self._svc_name_, '')) self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) win32event.SetEvent(self.stopEvt) def SvcDoRun(self): servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE, servicemanager.PYS_SERVICE_STARTED, (self._svc_name_, '')) self.main() def main(self): print('main start') self.server = ServerThread() self.server.start() print('waiting on win32event') win32event.WaitForSingleObject(self.stopEvt, win32event.INFINITE) self.server.exit() # raise SystemExit in inner thread print('waiting on thread') self.server.join() print('main done')if __name__ == '__main__': SMWinservice.parse_command_line()


