Dav*_*cks 6 python windows webserver
我有一个小的Web服务器应用程序,我用Python编写,从数据库系统获取一些数据并将其作为XML返回给用户.这部分工作正常 - 我可以从命令行运行Python Web服务器应用程序,我可以让客户端连接到它并获取数据.目前,要运行Web服务器,我必须以管理员用户身份登录到我们的服务器,并且必须手动启动Web服务器.我希望Web服务器在系统启动时自动启动为服务并在后台运行.
使用ActiveState的站点和StackOverflow中的代码,我非常清楚如何创建服务,我想我已经排序了 - 我可以安装并启动我的Web服务器作为Windows服务.但是,我无法弄清楚如何再次停止服务.我的Web服务器是从BaseHTTPServer创建的:
server = BaseHTTPServer.HTTPServer(('', 8081), SIMSAPIServerHandler)
server.serve_forever()
Run Code Online (Sandbox Code Playgroud)
自然地,serve_forever()调用使Web服务器处于无限循环中并等待HTTP连接(或ctrl-break按键,对服务无用).我从上面的示例代码中得到了一个想法,即你的main()函数应该处于一个无限循环中,只有当它处于"停止"状态时才会突破它.我的主要调用serve_forever().我有一个SvcStop功能:
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
exit(0)
Run Code Online (Sandbox Code Playgroud)
当我从命令行执行"python myservice stop"时,我似乎被调用了(我可以在其中放置一个产生输出到文件的调试行)但实际上并没有退出整个服务 - 后续调用"python myservice start" "给我一个错误:
启动服务时出错:服务实例已在运行.
随后的停止呼叫给了我:
停止服务时出错:此时服务无法接受控制消息.(1061)
我想我需要替换serve_forever(serve_until_stop_received,或其他),或者我需要一些修改SvcStop的方法,以便它停止整个服务.
这是一个完整的列表(我已经修剪了包含/注释以节省空间):
class SIMSAPIServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
try:
reportTuple = self.path.partition("/")
if len(reportTuple) < 3:
return
if reportTuple[2] == "":
return
os.system("C:\\Programs\\SIMSAPI\\runCommandReporter.bat " + reportTuple[2])
f = open("C:\\Programs\\SIMSAPI\\out.xml", "rb")
self.send_response(200)
self.send_header('Content-type', "application/xml")
self.end_headers()
self.wfile.write(f.read())
f.close()
# The output from CommandReporter is simply dumped to out.xml, which we read, write to the user, then remove.
os.unlink("C:\\Programs\\SIMSAPI\\out.xml")
return
except IOError:
self.send_error(404,'File Not Found: %s' % self.path)
class SIMSAPI(win32serviceutil.ServiceFramework):
_svc_name_ = "SIMSAPI"
_svc_display_name_ = "A simple web server"
_svc_description_ = "Serves XML data produced by SIMS CommandReporter"
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
exit(0)
def SvcDoRun(self):
import servicemanager
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,servicemanager.PYS_SERVICE_STARTED,(self._svc_name_, ''))
self.timeout = 3000
while 1:
server = BaseHTTPServer.HTTPServer(('', 8081), SIMSAPIServerHandler)
server.serve_forever()
def ctrlHandler(ctrlType):
return True
if __name__ == '__main__':
win32api.SetConsoleCtrlHandler(ctrlHandler, True)
win32serviceutil.HandleCommandLine(SIMSAPI)
Run Code Online (Sandbox Code Playgroud)
这就是我所做的:
我没有直接实例化 BaseHTTPServer.HTTPServer 类,而是编写了一个新的子类来发布“停止”方法:
class AppHTTPServer (SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
def serve_forever(self):
self.stop_serving = False
while not self.stop_serving:
self.handle_request()
def stop (self):
self.stop_serving = True
Run Code Online (Sandbox Code Playgroud)
然后,在您已有的 SvcStop 方法中,我调用该方法来中断serve_forever() 循环:
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
self.httpd.stop()
Run Code Online (Sandbox Code Playgroud)
(self.httpd是实现Web服务器的AppHTTPServer()实例)
如果您在后台线程上正确使用 setDaemon(),并正确中断服务中的所有循环,则指令
exit(0)
Run Code Online (Sandbox Code Playgroud)
在 SvcStop() 中应该不是必需的
| 归档时间: |
|
| 查看次数: |
6055 次 |
| 最近记录: |