在Windows中运行Python Web服务器作为服务

问题描述:

我有一个用Python编写的小型Web服务器应用程序,它从数据库系统获取一些数据并将其作为XML返回给用户。该部分工作正常 - 我可以从命令行运行Python Web服务器应用程序,我可以让客户端连接到它并获取数据。目前,要运行Web服务器,我必须以管理员用户身份登录到我们的服务器,并且必须手动启动Web服务器。我想让Web服务器在系统启动时作为服务自动启动并在后台运行。在Windows中运行Python Web服务器作为服务

ActiveState的网站,并*使用代码,我有一个如何去建立一个服务一个不错的想法,我想我已经得到了位排序 - 我可以安装并启动我的Web服务器作为Windows服务。然而,我不能弄清楚如何再次停止服务。我的Web服务器是从BaseHTTPServer创建:

server = BaseHTTPServer.HTTPServer(('', 8081), SIMSAPIServerHandler) 
server.serve_forever() 

的serve_forever()调用,很自然地,使Web服务器坐在一个无限循环,等待HTTP连接(或者用CTRL-Break按键,不实用一项服务)。我从上面的示例代码中了解到,您的main()函数应该处于无限循环中,并且只有在出现“停止”条件时才会突破它。我的主要调用serve_forever()。我有一个SvcStop功能:

def SvcStop(self): 
    self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) 
    exit(0) 

这似乎当我在命令行“蟒蛇为MyService一站式”得到所谓的(我可以把调试行中有产生输出到文件),但不实际上退出整个服务 - 后续调用“则将MyService蟒开始”给我一个错误:

Error starting service: An instance of the service is already running.

和后续调用停止给我:

Error stopping service: The service cannot accept control messages at this time. (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) 

这是我做的:

而是直接实例化类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 

然后,在方法SvcStop你已经有了,我认为这种方法打破serve_forever ()循环:

def SvcStop(self): 
    self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) 
    self.httpd.stop() 

(self.httpd是AppHTTPServer(实例)实现Web服务器)

如果使用setDaemon()正确的后台线程,并正确地中断所有的循环中该服务,然后在SvcStop指令

exit(0) 

()不应该是必要

+0

可以与你在同一范围[这里](http://*.com/questions/228问题帮助14933 /使服务器和控制台守护进程,作为服务型窗口) – 2014-04-03 08:12:58