【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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM