I did post this to the twisted list but as I said in the original post, I
think it is more a windows type issue than twisted.

What I am trying to work out is should I import twisted.reactor etc inside
the thread start in SvcDoRUn or import it globally as one of the examples
does.

And then should I be calling the reactor.fromthread in the SvcStop function.

If I import reactor in SvcDoRun will the SvcStop be called in the same
thread or not.

One of the examples import reactor globally, starts the reactor in SvcDoRun
- inside the thread -  and in SvcStop, calls the reactorfromthread. This to
me implies that SvcStop is in a different thread to SvcDoRun. But I could be
completely wrong on this point.

As you can see I am a little bit confused about what is happening here.


I have been looking for some info on running twisted as a Windows Service.

I have found various examples in mailing-lists and blogs that vary in what
seem to be important respects.

I have included them below as 3 examples.

The problem I have is working out which scheme or combination I should be
adopting.
I have tried out some of the options and they appear to work. But I need
something better than seems to work.

My gut reaction is that I should be putting all my imports into SvcDoRun,
since they will be used in the thread.

But if I import the reactor in SvcDoRun, should I be
using reactor.callfromthread(reactor.stop). I think not

I think the use of waitforobject is the right thing to do as well without
fully understanding it at the moment.

If anyone can throw some light on what to do I shall be very grateful.

It could be that I should post this question to python-windows mailing
list since it seems to me more pertinent to windows than twisted.

Thanks for any info.

John Aherne

Here is 1st example.

The reactor is imported globally not in SvcDoRun
It uses the waitforobject to detect stopping the service
The reactor.stop is calledfromthread


[Twisted-Python] How to run Twisted as a service in Windows?

Thomas Jacob jacob at internet24.de
Wed Aug 9 10:49:30 EDT 2006
Previous message: [Twisted-Python] How to run Twisted as a service in
Windows?
Next message: [Twisted-Python] How to run Twisted as a service in Windows?
Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
AFAIK, twistd doesn't provide direct support for Windows Services yet
(Is this planned?).

But you can easily wrap a reactor,run() yourself by doing something
like the following using the Win32-Python packages

import win32serviceutil
import win32service
import win32event

from twisted.internet import reactor

import sys


class IMSAgentBase(win32serviceutil.ServiceFramework):
    _svc_name_ = "myService"
    _svc_display_name_ = "My little Service"
    _svc_description_ = "My little Service" # Win2k or later
    _svc_deps_ = ["RpcSs"] # Start after the Network has come up...

    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)
        reactor.callFromThread(reactor.stop)
        win32event.SetEvent(self.hWaitStop)

    def SvcDoRun(self):

        # initialize your services here
        reactor.run()
        win32event.WaitForSingleObject(self.hWaitStop,win32event.INFINITE)

def HandleCommandLine(cls):
    win32serviceutil.HandleCommandLine(cls)


Run the above as a script.


Here is the 2nd example.

The imports are global not in SvcDoRun

And the reactor .stop is not called from thread.

And the wait for stop event is in a timeout loop

It uses waitforobject events

It sets installsignalhandlers to 0

 You can then test it out with the sample Echo client from the core docs.

 """qotdservice.py
 Sample Twisted Windows Service
 """

 # Service Utilities
 import win32serviceutil
 import win32service
 import win32event

 # Twisted imports
 from twisted.internet.protocol import Protocol, Factory
 from twisted.internet import reactor

 class QOTD(Protocol):

     def connectionMade(self):
         self.transport.write("An apple a day keeps the doctor away\r\n")
         self.transport.loseConnection()


 class WindowsService(win32serviceutil.ServiceFramework):
     _svc_name_ = "TwistedWin32Service"
     _svc_display_name_ = "Twisted Win32 Service"

     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)
         win32event.SetEvent(self.hWaitStop)

     def SvcDoRun(self):
         import servicemanager

         self.CheckForQuit()

         factory = Factory()
         factory.protocol = QOTD

         reactor.listenTCP(8007, factory)
         reactor.run(installSignalHandlers=0)


     def CheckForQuit(self):
         retval = win32event.WaitForSingleObject(self.hWaitStop, 10)
         if not retval == win32event.WAIT_TIMEOUT:
             # Received Quit from Win32
             reactor.stop()

         reactor.callLater(1.0, self.CheckForQuit)

 if __name__=='__main__':
     win32serviceutil.HandleCommandLine(WindowsService)


Here is  the 3rd example.

The imports are done in SvcDoRun.
There is no callfrom thread
It does not use the waitforobject

import sys, os
import win32serviceutil, win32service

class MyService(win32serviceutil.ServiceFramework):
    """NT Service."""

    _svc_name_ = "MyService"
    _svc_display_name_ = "MyService server"

    def SvcDoRun(self):
        import server
        f = open(os.path.join(server.rootPath, "cyberhigh.log"), 'a')
        from twisted.python.log import startLogging
        from twisted.application.app import startApplication
        from twisted.internet import reactor
        startLogging(f)
        startApplication(server.application, 0)
        reactor.run()

    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        from twisted.internet import reactor
        reactor.stop()

if __name__ == '__main__':</pre>
    win32serviceutil.HandleCommandLine(MyService)</pre>
_______________________________________________
python-win32 mailing list
python-win32@python.org
http://mail.python.org/mailman/listinfo/python-win32

Reply via email to