2008-09-30 6 views
6

में एक सेवा के रूप में एक पाइथन वेब सर्वर चलाना मेरे पास पाइथन में लिखा गया एक छोटा वेब सर्वर एप्लिकेशन है जो डेटाबेस सिस्टम से कुछ डेटा चलाता है और इसे उपयोगकर्ता के रूप में एक्सएमएल के रूप में लौटाता है। वह हिस्सा ठीक काम करता है - मैं पाइथन वेब सर्वर एप्लिकेशन को कमांड लाइन से चला सकता हूं और मैं क्लाइंट से कनेक्ट कर सकता हूं और डेटा वापस प्राप्त कर सकता हूं। फिलहाल, वेब सर्वर चलाने के लिए मुझे व्यवस्थापक सर्वर के रूप में हमारे सर्वर में लॉग इन करना होगा और मुझे मैन्युअल रूप से वेब सर्वर शुरू करना होगा। मैं चाहता हूं कि वेब सर्वर स्वचालित रूप से सिस्टम पर शुरू हो और सेवा में चलाए।विंडोज

ActiveState की साइट और StackOverflow से कोड का उपयोग करना, मैं कैसे एक सेवा बनाने के बारे में जाने के लिए की एक बहुत अच्छा विचार है, और मुझे मुझे लगता है कि थोड़ा अनुसार क्रमबद्ध मिल गया है लगता है - मैं स्थापित करने और एक के रूप में अपने वेब सर्वर शुरू कर सकते हैं विंडोज सेवा हालांकि, मैं यह नहीं समझ सकता कि सेवा को फिर से कैसे रोकें। मेरे वेब सर्वर एक BaseHTTPServer से बनाई गई है:

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

serve_forever() कॉल, स्वाभाविक रूप से पर्याप्त, अनंत लूप में वेब सर्वर बैठ बनाता है और HTTP कनेक्शन (या एक ctrl-तोड़ कुंजी दबाने, के लिए उपयोगी नहीं के लिए प्रतीक्षा एक सेवा)। मुझे ऊपर दिए गए उदाहरण कोड से यह विचार मिलता है कि आपका मुख्य() फ़ंक्शन एक अनंत लूप में बैठना चाहिए और जब इसे "स्टॉप" स्थिति में आता है तो केवल इसे तोड़ दें। मेरी मुख्य कॉल service_forever()।

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

कौन सा जब मैं कमांड लाइन से "अजगर MyService रोक" ऐसा कहा जाता है करने के लिए लगता है (मैं वहाँ में एक डिबग लाइन डाल सकते हैं कि एक फाइल करने के लिए उत्पादन का उत्पादन), लेकिन नहीं करता है: मैं एक SvcStop कार्य हो - वास्तव में पूरी सेवा से बाहर निकलने के "अजगर 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)

मुझे लगता है कि मैं या तो कुछ फिर से की जरूरत है service_forever (service_until_stop_received, या जो कुछ भी) के लिए प्लेसमेंट या मुझे SvcStop को संशोधित करने का कोई तरीका चाहिए, इसलिए यह पूरी सेवा को रोक देता है।

यहाँ एक पूरी सूची है (मैं छंटनी की है शामिल हैं/टिप्पणियों स्थान बचाने के लिए):

इसके बजाय सीधे वर्ग BaseHTTPServer.HTTPServer instancing की, मैं लिखने:

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) 

उत्तर

3

यह मैं क्या कर रहा है इसमें से एक नया वंशज है कि एक "रोक" विधि प्रकाशित करता है:

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 (का उदाहरण है) कि वेब सर्वर को लागू करता है)

आप setDaemon (का उपयोग करें) सही ढंग से पृष्ठभूमि धागे पर, और में सही ढंग से सभी छोरों को बाधित करते हैं सेवा है, तो शिक्षा

exit(0) 

SvcStop में() आवश्यक नहीं होना चाहिए

+0

आप एक ही संदर्भ [यहां] (http://stackoverflow.com/questions/228 में प्रश्न के साथ मदद कर सकते हैं 14,933/मेकअप सर्वर और कंसोल-डेमॉन के रूप में सेवा में विंडोज़) –