python写windows程序_【Python学习】Python 写Windows Service服务程序
如下遇到自己編寫的服務無法啟動
需要添加環境變量(標紅的)
C:\Python27\Scripts;C:\Python27\;C:\Python27\chromedriver.exe;C:\Python27\Lib\site-packages\win32;C:\Python27\Lib\site-packages\pywin32_system32;
1.需求
為什么要開發一個windows服務呢?之前做一個程序,必須要讀取指定目錄文件License, 因為其他程序也在讀取這指定目錄的License文件,且License不同時會修改License的內容,
修改了License后導致我們的程序無法運行,所以想做個windows 的服務時時檢測這個License文件是否被修改,如果檢測到被修改就覆蓋該License。
2.依賴的第三方庫
必須要借助第三方模塊pywin32
下載地址: https://pypi.python.org/pypi/pywin32/214
3.實現過程
實例化win32serviceutil.ServiceFramework的時候,windows系統會自動調用SvcDoRun方法,
這個函數的執行不可以結束,因為結束就代表服務停止。所以當我們放自己的代碼在SvcDoRun函數中執行的時候,必須確保該函數不退出,類似與這樣的效果:
1 def SvcDoRun(self):
2 while True:
3 self._LicenseExist()
4 time.sleep(2)
當停止服務的時候,系統會調用SvcDoStop函數,該函數通過設置標志位等方式讓SvcDoRun函數退出,就是正常的停止服務。
win32event.SetEvent(self.hWaitStop) 通過事件退出
服務操作命令:
1 #1.安裝服務
2
3 python PythonService.py install
4
5 #2.讓服務自動啟動
6
7 python PythonService.py --startup auto install
8
9 #3.啟動服務
10
11 python PythonService.py start
12
13 #4.重啟服務
14
15 python PythonService.py restart
16
17 #5.停止服務
18
19 python PythonService.py stop
20
21 #6.刪除/卸載服務
22
23 python PythonService.py remove
4.完整代碼:
1 # -*- coding: UTF8 -*-
2 #
3 import win32serviceutil
4 import win32service
5 import win32event
6 import winerror
7 import servicemanager
8 import os, sys, time
9
10 class PythonService(win32serviceutil.ServiceFramework):
11
12 _svc_name_ = "ALicense" # 服務名
13 _svc_display_name_ = "ALicense Is Exist " # 服務在windows系統中顯示的名稱
14 _svc_description_ = "ALicense Is Exist License windows" #服務的描述
15
16 def __init__(self, args):
17 win32serviceutil.ServiceFramework.__init__(self, args)
18 self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
19 self.License = self._LicenseExist()
20 self.run = True
21
22 def _LicenseExist(self):
23 is_exist=os.path.exists('C:\License.dat')
24 string_key='d8838bccad0c19e847b9e73f4432b951b6f035fd8c19f5474e30db5a0e4fa4c99b57c01af79161850b95d3f99a6b0b6074f18224ec7c44f28bc243be06f8f2b96e370f5ca724c01f1bd0e289afdd9eeef7e33d42a5113ddd4818a47b33449487baec2099a50d5e3dde32bdf66d979982a68d0d60a1200990ebf8a4827b7db3d1e83f9ad9d9946267fe830c48bbe025a5ebb99b85c7f1cf93de2beb22c8e9766e5ef526242b01f5251d8a768780026add2d2d8fb9ffccb86f8779221b01d206e586d96b83839b30006910a4bca6438fb5d5b2900431f8ecab50a9f18d0e7e8abec7b212fdc9ab667f08dd3eef14ecbdb24910466f45be92d0a085ff81d7362b828847c29be579942b63b9eb26b2441b5ef20f5a012431d263ded3f5fe434111b833612464bf4df18ae06c536b6895d240387774c3b438d5f0745c7a0d3ce963e82fc8df603f6fa526e8bd1fc51e2509e0840f3bbbde7bc3fec9e837b5aa744a9ae4449c974e26d787e475f73dbc3ee9c73cc258f38b79c413453fd4fe732bed57ba9d0312d2bcaf333a5c82d92a269a7ccaf27273a178feb95028f8f0805675a6199abbd8b47756b4543269a35025438794cd32410ac19c77526c4b94b93d091069056df1dda0f49298d753a317850c7104f94067ac9cc4d5b3d377f10627d21c12a4c066347eb05370fbe9e0658c1ec1803d43ed71509f5cdb25d60f505ef7527c405d3ea05bb381436dd3622484a1ff7263e4d93f275493332af3f77d28a13a0fa0eb810b7d25a378f6b8313ab3bcb44131ca3500670b0321aa95b077cef85d348e13315c2d2d42795e41569162986755709d099b59ee320e6caf422497234251d07d697bb3f3e5ad6d15d80fd85da016e7075bf84522aa6339e8b66ecd4b71d02fd01f4f57a0147ceaddbf9e5f32e7ec60ae35ff73d2f386d9d0133cb697731773b55fc2615c584e9f4013253d3fc53fa13a9e982a2493e1145861759c30cf9064d333bb184e378b52e7dd8bbbd0c17774549fabb44014dab2e0a903c53d0da1c9d3a223c69f3b9bcc7925ba21a464fc9fa43e20574ffedb7a27f2cd7ae7b6b46c5cb4e0b176ece7d59ff199b74b3436ead185df5c79d74b35d644bb02315130131772db21fcd1d535014b10c4cbbb8e1f847cd00be52992ab94a7b5a7b1c27d87abe3fc605972ceb3463a07924c816a04642adcabbc7b18a40a24a3af217d0390c1102cb5b4573b1816c76667f50d33631a97e986255644e8e0c26d63cd1f29f501ff51673509822c1bf8158ceee752024dcbe0e24941803ebd8afc0bded3598012ba5431060f0db7fad7fd4960972da9a6cfaa0850c43470498236ef7b22fbf79d491e054cf142815e6c04e573a52e22ccaa2d406167c6442db40456cd93752349b2968132388b51edbe13aa349abc34696453d1a4b39f8311284f8afbae'
25 if is_exist:
26 for line in open("C:\License.dat"):
27 if line!=string_key:
28 self.writer(string_key)
29 else:
30 self.writer(string_key)
31 # 寫入License
32 def writer(self, string_key):
33 f=open('C:\License.dat','w')
34 f.write(string_key)
35 f.close()
36
37 def SvcDoRun(self):
38 while self.run:
39 # 已經運行
40 self._LicenseExist()
41 time.sleep(2) #推遲調用線程的運行2秒
42
43 def SvcStop(self):
44 # 服務已經停止
45 self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
46 win32event.SetEvent(self.hWaitStop)
47 self.run = False
48
49 if __name__=='__main__':
50 if len(sys.argv) == 1:
51 try:
52 evtsrc_dll = os.path.abspath(servicemanager.__file__)
53 servicemanager.PrepareToHostSingle(PythonService)
54 servicemanager.Initialize('PythonService', evtsrc_dll)
55 servicemanager.StartServiceCtrlDispatcher()
56 except win32service.error, details:
57 if details[0] == winerror.ERROR_FAILED_SERVICE_CONTROLLER_CONNECT:
58 win32serviceutil.usage()
59 else:
60 win32serviceutil.HandleCommandLine(PythonService)
5.效果與問題
當直接運行py文件訪問是可以添加服務,且服務也可運行,但是使用pyinstaller打包exe后程序就不能正常執行,
提示:錯誤1053 服務沒有及時相應啟動或控制請求
google 后找到解決方法,
原理我也不是很懂,貌似是要在實例化windows服務類時候,監控服務調度
1 if len(sys.argv) == 1:
2 try:
3 evtsrc_dll = os.path.abspath(servicemanager.__file__)
4 servicemanager.PrepareToHostSingle(PythonService)
5 servicemanager.Initialize('PythonService', evtsrc_dll)
6 servicemanager.StartServiceCtrlDispatcher()
7 except win32service.error, details:
8 if details[0] == winerror.ERROR_FAILED_SERVICE_CONTROLLER_CONNECT:
9 win32serviceutil.usage()
10 else:
11 win32serviceutil.HandleCommandLine(PythonService)
pyinstaller 打包為控制臺文件
1 if __name__ == '__main__':
2 from PyInstaller.main import run
3 params=['windows_services_in_python.py', '-F', '-c', '--icon=favicon.ico']
4 run(params)
打包后CMD到改目錄:
放行殺毒軟件攔截
6.管理window服務操作
完整代碼:
1 #!/usr/bin/env python
2 # -*- coding: UTF8 -*-
3 #
4 import win32service
5 import win32con
6 import time, sys
7 import datetime
8 reload(sys)
9 sys.setdefaultencoding("utf8")
10 class ServiceManager(object):
11 """管理window服務"""
12
13 def __init__(self, name):
14 """
15 name: 服務的名稱
16 """
17 self.name = name
18
19 #啟動或停止服務時等待操作成功等待時間
20 self.wait_time = 0.5
21 #啟動或停止服務時最大等待時間,超過時返回超時提示
22 self.delay_time = 10
23 self.scm = win32service.OpenSCManager(None, None, win32service.SC_MANAGER_ALL_ACCESS)
24
25
26 if self.is_exists():
27 try:
28 self.handle = win32service.OpenService(self.scm, self.name, win32service.SC_MANAGER_ALL_ACCESS)
29 except Exception, e:
30 self.log(e)
31 else:
32 print '服務 %s 沒有安裝'.encode('gbk') % self.name
33
34
35 def is_stop(self):
36 """檢查服務是否停止"""
37 flag = False
38 try:
39 if self.handle:
40 ret = win32service.QueryServiceStatus(self.handle)
41 flag = ret[1] != win32service.SERVICE_RUNNING
42 except Exception, e:
43 self.log(e)
44 return flag
45
46 def start(self):
47 """開啟服務"""
48 try:
49 if self.handle:
50 win32service.StartService(self.handle, None)
51 except Exception, e:
52 self.log(e)
53 status_info = win32service.QueryServiceStatus(self.handle)
54
55 if status_info[1] == win32service.SERVICE_RUNNING:
56 return '啟動服務%s成功'.encode('gbk') % self.name
57 elif status_info[1] == win32service.SERVICE_START_PENDING:
58 #如果服務正在啟動中則延遲返回啟動信息,直到啟動成功,或返回啟動時間過長信息
59 start_time = datetime.datetime.now()
60 while True:
61 if (datetime.datetime.now() - start_time).seconds > self.delay_time:
62 return '啟動服務%s時間太長'.encode('gbk') % self.name
63
64 time.sleep(self.wait_time)
65 if win32service.QueryServiceStatus(self.handle)[1] == win32service.SERVICE_RUNNING:
66 return '啟動服務%s成功'.encode('gbk') % self.name
67 else:
68 return '啟動服務%s失敗'.encode('gbk') % self.name
69
70 def stop(self):
71 """停止服務"""
72 try:
73 status_info = win32service.ControlService(self.handle, win32service.SERVICE_CONTROL_STOP)
74 except Exception, e:
75 self.log(e)
76 if status_info[1] == win32service.SERVICE_STOPPED:
77 return '停止服務%s成功'.encode('gbk') % self.name
78 elif status_info[1] == win32service.SERVICE_STOP_PENDING:
79 start_time = datetime.datetime.now()
80 while True:
81 if (datetime.datetime.now() - start_time).seconds > self.delay_time:
82 return '停止服務%s時間太長'.encode('gbk') % self.name
83
84 time.sleep(self.wait_time)
85 if win32service.QueryServiceStatus(self.handle)[1] == win32service.SERVICE_STOPPED:
86 return '停止服務%s成功'.encode('gbk') % self.name
87 else:
88 return '停止服務%s失敗'.encode('gbk') % self.name
89
90 def restart(self):
91 """重啟服務"""
92 if not self.is_stop():
93 self.stop()
94 self.start()
95 return win32service.QueryServiceStatus(self.handle)
96
97 def status(self):
98 """獲取運行的狀態"""
99 try:
100 status_info = win32service.QueryServiceStatus(self.handle)
101 status = status_info[1]
102 if status == win32service.SERVICE_STOPPED:
103 return "STOPPED"
104 elif status == win32service.SERVICE_START_PENDING:
105 return "STARTING"
106 elif status == win32service.SERVICE_STOP_PENDING:
107 return "STOPPING"
108 elif status == win32service.SERVICE_RUNNING:
109 return "RUNNING"
110 except Exception, e:
111 self.log(e)
112
113 def close(self):
114 """釋放資源"""
115 try:
116 if self.scm:
117 win32service.CloseServiceHandle(self.handle)
118 win32service.CloseServiceHandle(self.scm)
119 except Exception, e:
120 self.log(e)
121
122 def is_exists(self):
123 """windows服務是否已安裝"""
124 statuses = win32service.EnumServicesStatus(self.scm, win32service.SERVICE_WIN32, win32service.SERVICE_STATE_ALL)
125 for (short_name, desc, status) in statuses:
126 if short_name == self.name:
127 return True
128 return False
129
130 def log(self, exception):
131
132 print(exception)
133
134
135
136 if __name__=='__main__':
137
138 app= ServiceManager('AAaservice')
139 msg= app.is_exists() # 判斷是否安裝 (以下操作必須先判斷服務是否存在)
140 #msg= app.is_stop() # 判斷服務是否停止
141 #msg= app.status() # 查看服務的狀態
142 #msg= app.start() # 開啟服務
143 #msg= app.stop() # 暫停服務 (服務開啟才能停止,else error)
144 #msg= app.restart() # 重啟服務
145
146 print(msg)
7.參考地址:
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的python写windows程序_【Python学习】Python 写Windows Service服务程序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python中怎么比较两个列表的大小_P
- 下一篇: orcad如何设置模块化设计_充气膜结构