[Twisted-Python] Re: mktap/twistd in a Windows service

David Bolen db3l.net at gmail.com
Sun Nov 4 14:55:23 EST 2007


Paul Moore <pf_moore at yahoo.co.uk> writes:

> I want to run a tiny non-authoritative DNS server on my PC. I've never
> done this before, but twisted names looks ideal. The documentation
> (http://twistedmatrix.com/projects/names/documentation/howto/names.html)
> says I just need to do
>
>     mktap dns --recursive --cache
>     twistd -f dns.tap
>
> and indeed this works fine. I seem to recall some time ago seeing
> postings to the effect that tap format files were out of favour, but I
> don't follow the twisted list much, so I don't know if this is still
> true. Nevertheless, it works so who cares?
>
> However, I want to run this as a Windows service. Ideally, twistd
> would have a --install-service flag or something, but it doesn't so I
> went looking, and found postings covering tap2ntsvc which creates
> services from tap files, but it seems to have been replaced by ntsvc,
> which only handles .tac files :-(

For what it's worth, I rarely use twistd for my Twisted applications,
and it's not that much work to run Twisted-based code as an NT service
without any external utilities.

You can set things up with the pywin32's service support
(win32service/util), and just have your main entry point run Twisted's
reactor.  The shutdown code stops the reactor and also terminates the
service.  Note that service startup runs the main entry point in a
second thread, but that's the "main" thread from Twisted's
perspective.  It does mix up signal handling under Windows, so I
typically disable that in the reactor.  Also, service control messages
(like stop) are run in the service thread (true application main
thread), so you need to call into Twisted's thread to stop the
reactor.

Here's a tiny startup script that provides service support for some
application - I've removed any special logging initialization and
registry parameter support for clarity.

          - - - - - - - - - - - - - - - - - - - - - - - - -

import os, sys
import win32service,win32serviceutil

from twisted.internet import reactor
from twisted.python import log

# Ensure basic thread support is enabled for twisted
from twisted.python import threadable
threadable.init(1)


class Service(win32serviceutil.ServiceFramework):

    _svc_name_ = '{servicename}'
    _svc_display_name_ = '{Display name for Service}'

    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        log.msg('Stopping {server}...')
        reactor.callFromThread(reactor.stop)

    def SvcDoRun(self):

        #
        # ... Initialize application here
        #

        log.msg('{Server} running...')
        reactor.run(installSignalHandlers=0)


if __name__ == "__main__":
    win32serviceutil.HandleCommandLine(Service)

              - - - - - - - - - - - - - - - - - - - - - - - - -

The above provides for install/uninstall based on the default command
line handling in win32serviceutil, and of course normal Windows
control ("net start", "net stop") afterwards.  Registering as a Python
module only runs on the machine with Python/pywin32 installed, but you
can package the above with something like py2exe.

You can then get as complicated as you want from here.  There are some
helper functions in win32serviceutil (Get/SetServiceCustomOption) that
can simplify storing startup information in the registry if you like.

Alternatively, I've implemented my own equivalent to HandleCommandLine
in some cases where I wanted better control (or preferred "--install"
to just "install"), wanted to work in a stdin/stdout debug mode when
run directly, or needed to synchronize startup handling with the
py2exe version, when I packaged the service into an executable.

Note that I'm not sure how the above plays with Twisted's service
framework, as I never got comfortable with using it.  But aside from that
anything beyond the basics above are general python service questions,
and not specific to Twisted applications.

-- David





More information about the Twisted-Python mailing list