We had project last friday to write a
windows service that would poll an Exchange mail box and write to a database. It
was executed in C#. Well... i got thinking... hmmm... can't python be used to do
this? Because if it can, then that project would not last more than a couple of
hours (actualy, the C# project shouldn't also last more than a couple of hours
if you know what you'r doing, but hey.. i have to have something to say about
why i decided to do it in Python write? i mean.... I LOVE Python may not cut it
for some folks :) )
OK... lets get to the meat of it.
I first hit
google, looking for links to python and windows services. I then found some
mailing list archives and in one of them, there was a reference to a chapter on
Windows Services in the book, Programming Python on Win32.
Well... i had
access to the book, and went headlong. Long and short of it, 15 mins of perusing
latter, I had a windows service running. Lets attempt to get this stuff to work
together now.
First there are two very important modules that helps
our lives out. win32service and win32serviceutil
We're going to write a
service that just writes to the event log every 10 seconds. U'll have to stop
this service soon or else, you'll run out of EvenLog space ;)
First some
important pre-parations and background on python-windows services. There is a
program called pythonservice.exe, that actually handles everything that concerns
windows services written in Python. I'm walking a thin rope here with this
explanation now, but this is how i understand it, just don't quote me in a
conference where there are other Pythonistas and Lords Of the Eggs, I'll deny it
vehemently ;)
The way i figure it, pythonservice.exe is to python
services what the usual python.exe is for all other normal python scripts.
Normally on windows, once .py is associated with python.exe, each time you run a
script, the python intepreter, python.exe is called to 'intepret' it. For
services, apparently some funky stuff goes on, so instead of calling python.exe
as the intepreter, pythonservice.exe is called as the intepreter (well, not
exactly intepreter i guess, but it is the process that runs the services.) You
can also look at it like this: You say service start, windows identifies it as a
python service, and starts pythonservice.exe passing it parameters to find the
service itself. Pythonservice.exe locates the service, and starts it. As far as
windows is concerned, it is running a process called PythonService.exe (You'll
see that without special tricks, when writting to eventlog, PythonService is the
one that does the writing)
Now the preceeding means that windows has to
know to associate python services with pythonservice.exe . This is essentially
called registeration. So pythonservice.exe must be registered with windows to
handle python windows services. to do that, locate where the python win32
extensions are on your box. They'll probably be in your site-packages folder.
Look for the win32\ subdirectory, and you'll locate pythonservice.exe sitting
somewhere there:
Mine is at
C:\Python24\Lib\site-packages\win32\pythonservice.exe
you can change to
that directory:
C:\Python24\Lib\site-packages\win32
and then do:
pythonservice.exe /register
You should see a message about registering
the Python Service Manager.
After that, if there are no errors, we're
ready to plunge.
First, we need to import the two all important
modules.
For those who don't understand Python... the lines beginning
with #, are just comments.
import win32service
import
win32serviceutil
import time
#at this point. We're ready to
go.
#Put simply, a python windows service inherits from
win32serviceutils.ServiceFramework
#simply extending that class, sets up all
you ever need to do.
class
aservice(win32serviceutil.ServiceFramework):
_svc_name_ =
"aservice"
_svc_display_name_ = "aservice - It Does nothing"
def
__init__(self,args):
win32serviceutil.ServiceFramework.__init__(self,args)
#at
this point service is created pefectly.
#you could stop here and jump to
setting up the '__main__' section,
#but you wont be able to stop your
service, and it won't do anything.
#at the very least, you need to implement
SvcDoRun() and better still SvcStop():
#This next attribute is used when its
stopping time.
self.isAlive = True
def SvcDoRun(self):
import
servicemanager
while self.isAlive:
#remember when i said you needed only
two modules?
#well... i think i lied. If you're going to do
anything
#usefull, you're going to obviously need more modules.
#This next
module servicemanager, has some funny
#properties that makes it only to be
visible when
#the service is properly setup. This means it can't be
imported
#in normal python programs, and can't even be imported
#in the
Global Namespace, but only in local functions that
#will be called after the
service is setup. Anyway,
#this module contains some utilities for writing to
EventLog.
servicemanager.LogInfoMsg("aservice - is alive and
well")
time.sleep(10)
servicemanager.LogInfoMsg("aservice -
Stopped")
def SvcStop(self):
#before you stop, you'll want to inform
windows that
#you've recieved a stop signal, and you're trying to
stop.
#in the windows Service manager, this is what shows the status message
as
#'stopping'. This is important, since SvcDoRun() may take sometime before
it stops.
import servicemanager
servicemanager.LogInfoMsg("aservice -
Recieved stop
signal")
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
self.isAlive
= False #this will make SvcDoRun() break the while loop at the next
iteration.
if __name__ ==
'__main__':
win32serviceutil.HandleCommandLine(aservice) #this line sets it
all up to run properly.
Uhh... just incase you haven't guessed.
That is all for the service.
The next part is installing and starting it. You
can save this as aservice.py
cd to the directory where it is saved and
do:
aservice.py install
Note that 'aservice.py remove' will remove
the service
you can start and stop with Windows Service manager
or:
aservice.py start
and
aservice.py stop
OK...
that's it... play around, flesh out... anything.
You may or may not have
figured out that the entire functionality of the serivice gets started from
SvcDoRun()
That's all folks... i hope this is usefull :)
Hey... i
just had a brainwave. I'll repeat the code here without any comments
:)
1 import win32service
2 import win32serviceutil
3 import time
4
5 class aservice(win32serviceutil.ServiceFramework):
6 _svc_name_ = "aservice"
7 _svc_display_name_ = "aservice - It Does nothing"
8
9 def __init__(self,args):
10 win32serviceutil.ServiceFramework.__init__(self,args)
11 self.isAlive = True
12
13 def SvcDoRun(self):
14 import servicemanager
15
16 while self.isAlive:
17 servicemanager.LogInfoMsg("aservice - is alive and well")
18 time.sleep(10)
19 servicemanager.LogInfoMsg("aservice - Stopped")
20
21 def SvcStop(self):
22 import servicemanager
23
24 servicemanager.LogInfoMsg("aservice - Recieved stop signal")
25 self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
26 self.isAlive = False
27
28 if __name__ == '__main__':
29 win32serviceutil.HandleCommandLine(aservice)
30
Note that
if you're going to copy and paste this stuff, you may have some white space
issues, since i'm just typing straight and editing here.
posted on 2009-08-01 14:42
老马驿站 阅读(828)
评论(0) 编辑 收藏 引用 所属分类:
python