سؤال

لدي الصغيرة ملقم ويب التطبيق لقد مكتوبة في بيثون أن يذهب ويحصل على بعض البيانات من قاعدة بيانات النظام يعود إلى المستخدم كما XML.هذا الجزء يعمل بشكل جيد - لا يمكن تشغيل الثعبان ملقم ويب التطبيق من سطر الأوامر يمكن للعملاء الاتصال به والحصول على البيانات مرة أخرى.في لحظة تشغيل ملقم ويب يجب أن تكون تسجيل الدخول إلى الملقم كمسؤول المستخدم يجب أن يدويا بدء تشغيل ملقم ويب.أريد أن يكون ملقم ويب تلقائيا على نظام مجموعة خدمة تشغيل في الخلفية.

باستخدام رمز من ActiveState'ق الموقع ، ستاكوفيرفلوو, لدي فكرة جيدة عن كيفية التوجه نحو إنشاء خدمة وأعتقد أنني قد حصلت على هذا قليلا فرز - لا يمكن تثبيت على ملقم ويب مثل خدمة Windows.لا أستطيع ، ومع ذلك ، معرفة كيفية إيقاف الخدمة مرة أخرى.بلدي ملقم ويب التي تم إنشاؤها من BaseHTTPServer:

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

على serve_forever() تتصل بطبيعة الحال يجعل ملقم ويب الجلوس في حلقة لا نهائية وانتظر HTTP اتصالات (أو ctrl-كسر keypress, ليس من المفيد الخدمة).أنا على فكرة من التعليمة البرمجية الموجودة في المثال أعلاه الرئيسي الخاص بك() وظيفة من المفترض أن يجلس في حلقة لا نهائية فقط الخروج من ذلك عندما يتعلق الأمر عبر "وقف" حالة.بلدي الرئيسية المكالمات serve_forever().لدي SvcStop وظيفة:

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

الذي يبدو للحصول على ما يسمى عندما أفعل "الثعبان myservice وقف" من سطر الأوامر (لا يمكن وضع خط التصحيح في هناك التي تنتج الإخراج إلى ملف) ولكن في الواقع لا خروج كل خدمة المكالمات اللاحقة إلى "الثعبان myservice ابدأ" يعطيني خطأ:

خطأ في بدء تشغيل الخدمة:مثيل الخدمة قيد التشغيل بالفعل.

وما تلاها من دعوات لوقف يعطيني:

خطأ إيقاف الخدمة:الخدمة لا يمكن أن نقبل رسائل التحكم في هذه الوقت.(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, أكتب سليل من ذلك أن تنشر رسالة "stop" الطريقة:

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()

(النفس.httpd هو مثيل AppHTTPServer() التي تطبق webserver)

إذا كنت تستخدم setDaemon() بشكل صحيح على خلفية المواضيع و يقطع بشكل صحيح جميع الحلقات في الخدمة ، ثم التعليم

exit(0)

في SvcStop() يجب أن لا يكون ضروريا

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top