我有一个基本的fastapi
main.py
如下:
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
origins = ["*"]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/")
def read_root():
return {"Hello": "World"}
和
win_service.py
如下:
import win32serviceutil
import win32service
import win32event
import servicemanager
import socket
import os
from threading import Thread
import uvicorn
class AppServerSvc(win32serviceutil.ServiceFramework):
_svc_name_ = "ABCD"
_svc_display_name_ = "ABCD Windows Service"
_svc_description_ = "A FastAPI application running as a Windows Service"
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):
servicemanager.LogMsg(
servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_, "")
)
self.main()
def main(self):
def start_server():
os.chdir(os.path.dirname(os.path.abspath(__file__)))
uvicorn.run("main:app", host="0.0.0.0", port=8000)
server_thread = Thread(target=start_server)
server_thread.start()
win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE)
server_thread.join()
if __name__ == '__main__':
win32serviceutil.HandleCommandLine(AppServerSvc)
使用 Windows 11 和 Python 版本 3.9。当我尝试使用管理cmd安装(
python win_service.py install
)并调试(python win_service.py debug
)时,它可以工作并且我可以在http://localhost:8000上访问它
当我启动(
python win_service.py start
)时,它就会启动,并且在Windows事件查看器中日志显示The ABCD service has started.
,但无法通过http://localhost:8000访问它
当它作为服务运行时,我如何访问它?
最终创建了一个解决方法,将 fastapi 作为子进程启动:
import os
import win32serviceutil
import win32service
import win32event
import socket
import subprocess
class AppServerSvc(win32serviceutil.ServiceFramework):
_svc_name_ = "ABCD"
_svc_display_name_ = "ABCD Windows Service"
_svc_description_ = "A FastAPI application running as a Windows Service"
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
socket.setdefaulttimeout(60)
self.is_running = True
self.process = None
def SvcDoRun(self):
self.ReportServiceStatus(win32service.SERVICE_RUNNING)
self.main()
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
self.is_running = False
if self.process:
self.process.terminate()
self.process.wait()
win32event.SetEvent(self.hWaitStop)
def main(self):
uvicorn_location = r"C:\Users\username\AppData\Local\Programs\Python\Python39\Scripts\uvicorn.exe"
command = [
uvicorn_location,
"main:app",
"--host",
"0.0.0.0",
"--port",
"8000"
]
working_directory = r"E:\path-to-fastapi-backend"
os.chdir(working_directory)
self.process = subprocess.Popen(command)
while self.is_running:
rc = win32event.WaitForSingleObject(self.hWaitStop, 5000)
if rc == win32event.WAIT_OBJECT_0:
break
if __name__ == "__main__":
win32serviceutil.HandleCommandLine(AppServerSvc)