i have a basic fastapi main.py
as following:
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"}
and a win_service.py
as following:
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)
using windows 11 & python version 3.9. when i try to install (python win_service.py install
) using admin cmd and debug (python win_service.py debug
) it works & i can access it on http://localhost:8000
when i start (python win_service.py start
), it gets started and in windows event viewer the log shows The ABCD service has started.
but it's not accessable at http://localhost:8000
how can i access it, when it's running as a service?
finally created a work around, that starts fastapi as a sub-process:
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)