Un ejemplo completo de pywin32 usando bucle o subproceso
Después de trabajar en esto por unos días, aquí está la respuesta que hubiera deseado encontrar, usando pywin32 para mantenerlo agradable y autónomo.
Este es un código de trabajo completo para una solución basada en bucles y una basada en subprocesos. Puede funcionar tanto en python 2 como en 3, aunque solo he probado la última versión en 2.7 y Win7. El bucle debería ser bueno para el código de sondeo, y la banda de rodadura debería funcionar con más código similar al servidor. Parece funcionar bien con el servidor de camarera wsgi que no tiene una forma estándar de cerrar con gracia.
También me gustaría señalar que parece haber muchos ejemplos, como este, que son casi útiles, pero en realidad engañosos, porque han cortado y pegado otros ejemplos a ciegas. Podría estar equivocado. pero ¿por qué crear un evento si nunca lo esperas?
Dicho esto, todavía siento que estoy en un terreno algo inestable aquí, especialmente con respecto a cuán limpia es la salida de la versión de hilo, pero al menos creo que no hay nada engañoso aquí.
Para ejecutar, simplemente copie el código a un archivo y siga las instrucciones.
actualizar:
Use una bandera simple para terminar el hilo. Lo importante es que se imprime "hilo hecho".
Para un ejemplo más elaborado que sale de un hilo de servidor no cooperativo, vea mi publicación sobre el servidor de camarera wsgi .
# uncomment mainthread() or mainloop() call below
# run without parameters to see HandleCommandLine options
# install service with "install" and remove with "remove"
# run with "debug" to see print statements
# with "start" and "stop" watch for files to appear
# check Windows EventViever for log messages
import socket
import sys
import threading
import time
from random import randint
from os import path
import servicemanager
import win32event
import win32service
import win32serviceutil
# see http://timgolden.me.uk/pywin32-docs/contents.html for details
def dummytask_once(msg='once'):
fn = path.join(path.dirname(__file__),
'%s_%s.txt' % (msg, randint(1, 10000)))
with open(fn, 'w') as fh:
print(fn)
fh.write('')
def dummytask_loop():
global do_run
while do_run:
dummytask_once(msg='loop')
time.sleep(3)
class MyThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
global do_run
do_run = True
print('thread start\n')
dummytask_loop()
print('thread done\n')
def exit(self):
global do_run
do_run = False
class SMWinservice(win32serviceutil.ServiceFramework):
_svc_name_ = 'PyWinSvc'
_svc_display_name_ = 'Python Windows Service'
_svc_description_ = 'An example of a windows service in Python'
@classmethod
def parse_command_line(cls):
win32serviceutil.HandleCommandLine(cls)
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
self.stopEvt = win32event.CreateEvent(None, 0, 0, None) # create generic event
socket.setdefaulttimeout(60)
def SvcStop(self):
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STOPPED,
(self._svc_name_, ''))
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.stopEvt) # raise event
def SvcDoRun(self):
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_, ''))
# UNCOMMENT ONE OF THESE
# self.mainthread()
# self.mainloop()
# Wait for stopEvt indefinitely after starting thread.
def mainthread(self):
print('main start')
self.server = MyThread()
self.server.start()
print('wait for win32event')
win32event.WaitForSingleObject(self.stopEvt, win32event.INFINITE)
self.server.exit()
print('wait for thread')
self.server.join()
print('main done')
# Wait for stopEvt event in loop.
def mainloop(self):
print('loop start')
rc = None
while rc != win32event.WAIT_OBJECT_0:
dummytask_once()
rc = win32event.WaitForSingleObject(self.stopEvt, 3000)
print('loop done')
if __name__ == '__main__':
SMWinservice.parse_command_line()