最近在學習在windows平台用flask框架提供Restful API服務,需要使得flask的windows應用能夠開機自動運行,並且后台運行,所以通過service來實現。
首先嘗試的是在自己派生的serivice類的中直接調用 create_app(debug=True).run(host='0.0.0.0', port=5000) 的方式啟動flask。
參考代碼:
import win32serviceutil import win32service import win32event import win32evtlogutil import servicemanager import socket import time import os import sys from flask import logging, app, Flask from run import create_app sys.path.append(os.path.dirname(__name__)) def main(): # app.run(host="0.0.0.0", port=5000) # 服務運行函數 # launch() create_app(debug=True).run(host='0.0.0.0', port=5000) class MySvc(win32serviceutil.ServiceFramework): _svc_name_ = "my web service" # 服務名 _svc_display_name_ = "my web service" # 描述 def __init__(self, *args): win32serviceutil.ServiceFramework.__init__(self, *args) self.hWaitStop = win32event.CreateEvent(None, 0, 0, None) socket.setdefaulttimeout(5) self.stop_requested = False def SvcStop(self): self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) win32event.SetEvent(self.hWaitStop) self.ReportServiceStatus(win32service.SERVICE_STOPPED) # logging.info('Stopped service ...') self.stop_requested = True def SvcDoRun(self): servicemanager.LogMsg( servicemanager.EVENTLOG_INFORMATION_TYPE, servicemanager.PYS_SERVICE_STARTED, (self._svc_name_, '') ) main() if __name__ == '__main__': win32serviceutil.HandleCommandLine(MySvc)
但是啟動service的時候一直報錯如下,參考了很多種方法一直解決不了

接下來嘗試用subprocess的方法拉起進程,成功!
class MyService(PySvc): def start(self): self.child = subprocess.Popen("python run.py", cwd="C:\\mytest") logging.warning('child pid is %s',self.child.pid) # TODO: add run service code def stop(self): self.child.kill()
但是在stop的發現有一個python進程不能被kill。原因應該是flask本身會啟動一個python子進程,相當於subprocess起了一個子進程執行 python run.py,在run.py啟動flask的時候又啟動了一個子進程,而child.kill只能殺死由subprocess啟動的子進程,改成用taskkill就好了。
class MyService(PySvc): def start(self): self.child = subprocess.Popen("python run.py", cwd="C:\\mytest") logging.warning('child pid is %s',self.child.pid) # TODO: add run service code def stop(self): #self.child.kill() os.system("taskkill /t /f /pid %s" % self.child.pid)
完整代碼如下:
import os import signal import subprocess from time import sleep import win32service import win32serviceutil import win32event import logging logging.basicConfig(filename='C:\\app.log', filemode='w', format='%(name)s - %(levelname)s - %(message)s') logging.warning('This will get logged to a file') class PySvc(win32serviceutil.ServiceFramework): _svc_name_ = "ServicePython" # NET START/STOP the service by the following name _svc_display_name_ = "ServicePython Service" # name in the Service Control Manager (SCM) _svc_description_ = "This service writes stuff to a file" # description in the SCM def __init__(self, args): win32serviceutil.ServiceFramework.__init__(self, args) # create an event to listen for stop requests on , 所以也是可以和client進行通信的 self.hWaitStop = win32event.CreateEvent(None, 0, 0, None) def SvcDoRun(self): # 啟動時調用 import servicemanager self.start() win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE) def SvcStop(self): # 關閉時調用 self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) # tell the SCM win32event.SetEvent(self.hWaitStop) # fire the stop event self.stop() class MyService(PySvc): def start(self): self.child = subprocess.Popen("python run.py", cwd="C:\\mytest") logging.warning('child pid is %s',self.child.pid) # TODO: add run service code def stop(self): os.system("taskkill /t /f /pid %s" % self.child.pid) # TODO:shut down the running flask web service if __name__ == '__main__': win32serviceutil.HandleCommandLine(MyService)
