使用循环或子线程的完整pywin32示例
经过几天或几天的研究之后,这是我希望找到的答案,使用pywin32使其保持良好状态并自成一体。
这是一个基于循环和一个基于线程的解决方案的完整工作代码。尽管我只测试了2.7和Win7的最新版本,但它可能同时在python 2和python 3上运行。该循环应适合轮询代码,而踏步应该可以处理更多类似于服务器的代码。这似乎与没有标准方法正常关闭的女服务员 wsgi服务器很好地配合。
我也想请注意,似乎有实例负载在那里,就像这是几乎是有用的,但在现实中误导,因为他们有剪切和粘贴盲目其他例子。我可能是错的。但是,如果您从不等待,为什么还要创建一个事件?
话虽如此,我仍然觉得我在这里有些不稳定,特别是关于线程版本的退出情况有多干净的问题,但至少我相信这里没有误导之处。
要运行,只需将代码复制到文件中,然后按照说明进行操作即可。
更新:
使用一个简单的标志终止线程。重要的一点是“线程完成”打印。
有关从不合作的服务器线程退出的更详细的示例,请参阅我关于女服务员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()