Un esempio completo di pywin32 che utilizza loop o subthread
Dopo aver lavorato su questo per alcuni giorni, ecco la risposta che avrei voluto trovare, usando pywin32 per mantenerlo piacevole e autonomo.
Questo è un codice di lavoro completo per una soluzione basata su loop e una basata su thread. Può funzionare sia su Python 2 che su 3, anche se ho testato solo l'ultima versione su 2.7 e Win7. Il ciclo dovrebbe essere buono per il codice di polling e il battistrada dovrebbe funzionare con più codice simile al server. Sembra funzionare bene con il server wsgi cameriera che non ha un modo standard per chiudere con grazia.
Vorrei anche notare che sembrano esserci molti esempi là fuori, come questo che sono quasi utili, ma in realtà fuorvianti, perché hanno tagliato e incollato ciecamente altri esempi. Potrei sbagliarmi. ma perché creare un evento se non lo aspetti mai?
Detto questo, mi sento ancora su un terreno un po 'traballante qui, soprattutto per quanto riguarda l'uscita pulita dalla versione del thread, ma almeno credo che qui non ci sia nulla di fuorviante .
Per eseguire è sufficiente copiare il codice in un file e seguire le istruzioni.
aggiornare:
Usa un semplice flag per terminare il thread. La parte importante è che "thread thread" viene stampato.
Per un esempio più elaborato che esce da un thread del server non collaborativo, vedere il mio post sul server wsgi della cameriera .
# 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()