Writing Python applications under windows is quite simple, maybe you didn't use windows to develop your application (as I do most times), the code, what you want to do with your application is up to you, and I'm not goint to touch the programming techniques for developing windows applications, Just, create a simple -and useles- win32 service that will help you to uderstand how to create your very own windows service.
First, every single program that you create with python and compile with py2exe and does run well, may be a win32 service, it may be a program that fetches the RSS xml feed for , maybe is a more complex program to generate some files and then send them to another server, maybe is a simple program to remind you to sand up an walk 10 minutes.
Said that we don't really need to create a program thinking on it as a service, we will create a simple program and test it using the python interpreter, who needs to compile?, well, we need it, but just when we are sure that our program performs well.
#!/usr/bin/env python
import time
import thread
import os
import sys
class service_test:
def __init__(self):
thread.start_new(self.do_something, tuple())
while True:
if getattr(sys,'stopservice', False):
sys.exit()
time.sleep(0.3)
def do_something(self):
'''
Do something
'''
while True:
fname ='C:\\\\test.txt'
f = open(fname , 'a')
f.write(time.time())
f.close()
time.sleep(1)
if __name__ == "__main__":
tst = service_test()
import win32serviceutil
import win32service
import win32event
import os
import sys
import time
sys.stopservice = "false"
def main():
'''
Modulo principal para windows
'''
sys.path.insert(0,os.getcwd())
import service_module
a = service_module.service_test()
class ServiceLauncher(win32serviceutil.ServiceFramework):
_svc_name_ = 'ServiceTest'
_scv_display_name_ ='Servicio de pruebas'
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)
sys.stopservice = "true"
win32event.SetEvent(self.hWaitStop)
def SvcDoRun(self):
main()
Then, we have two methods. one SvcStop, this method will be called when we want to stop the service in the service mananger. As our program is not running here, is safe to communicate with it by some method, I use a variable stored in "sys" which is "pooled" on the main program to know when it's time to stop the program.
THe method SvcDoRun is quite explicit, it starts the program. Now, you guess that when you start your service must be doing something, even sleeping, because, if it stops, then an error message will be saved in the Windows logs.
Ok, we have our program and our wrapper class, but, did I said that Windows cannot load a python scritp as a service?. Well, we need to compile it. here is when py2exe comes in.
Py2Exe will help us to convert those scripts in a binary for windows, a simple binary for execution or a Windows service :-D. I use this script to create my windows services, py2exe makes use of the distutils and hence a setup.py script must be used to compile the our scripts. check the next code that will help you to create console programs and win32 services.
import sys
buildservice = True
if '--no-service' in sys.argv[1:]:
buildservice = False
sys.argv = [k for k in sys.argv if k != '--no-service']
print sys.argv
from distutils.core import setup
import os
import py2exe
import glob
import shutil
sys.path.insert(0,os.getcwd())
def getFiles(dir):
"""
Retorna una tupla de tuplas del directorio
"""
# dig looking for files
a= os.walk(dir)
b = True
filenames = []
while (b):
try:
(dirpath, dirnames, files) = a.next()
filenames.append([dirpath, tuple(files)])
except:
b = False
return filenames
DESCRIPTION = 'Servicio de pruebas'
NAME = 'servicetest'
class Target:
def __init__(self,**kw):
self.__dict__.update(kw)
self.version = "1.00.00"
self.compay_name = ""
self.copyright = "(c) 2009, Marco Islas"
self.name = NAME
self.description = DESCRIPTION
my_com_server_target = Target(
description = DESCRIPTION,
service = ["service_module"],
modules = ["service_module"],
create_exe = True,
create_dll = True)
if not buildservice:
print 'Compilando como ejecutable de windows...'
setup(
name = NAME ,
description = DESCRIPTION,
version = '1.00.00',
console = ['service_module.py'],
zipfile=None,
options = {
"py2exe":{"packages":"encodings",
"includes":"win32com,win32service,win32serviceutil,win32event",
"optimize": '2'
},
},
)
else:
print 'Compilando como servicio de windows...'
setup(
name = NAME,
description = DESCRIPTION,
version = '1.00.00',
service = [{'modules':["ServiceLauncher"], 'cmdline':'pywin32'}],
zipfile=None,
options = {
"py2exe":{"packages":"encodings",
"includes":"win32com,win32service,win32serviceutil,win32event",
"optimize": '2'
},
},
)
I hope this article and the code above help you, If you have a question or some comment with this, plese use the comment form in the post associated to this article.