【windows&flask】flask通过service自动运行
最近在学习在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)