📝
PythonでWindows サービス(SocketServer)を作成
Windows 2019Server(Windows10でも同じ)
Python 3.7.8
Pythonをインストール
python-3.7.8.exeを使用してインストール
今回は諸事情で32bit版をインストールしていますが64bit版でも問題ないはず
ライブラリのインストール
Windowsサービスということで今回はpywin32を使用する
pip install pywin32
※もし上記のコマンドで64bit版のpywin32がインストールされてしまう場合は32bit版の.whlファイルを事前に準備し直接指定してインストールを行いましょう
環境変数
以下の6つの環境変数が設定されていることを確認する
# ユーザ環境変数.path
C:\Users\<ユーザ名>\AppData\Local\Programs\Python\Python37-32\Scripts\
C:\Users\<ユーザ名>\AppData\Local\Programs\Python\Python37-32\
# システム環境変数.path
C:\Users\<ユーザ名>\AppData\Local\Programs\Python\Python37-32\Scripts\
C:\Users\<ユーザ名>\AppData\Local\Programs\Python\Python37-32\
C:\Users\<ユーザ名>\AppData\Local\Programs\Python\Python37-32\Lib\site-packages\pywin32_system32
C:\Users\<ユーザ名>\AppData\Local\Programs\Python\Python37-32\Lib\site-packages\win32
実行ファイル
今回はタイトルにもある通りSocketServerサービスをPythonで実装する
必要なモジュールは以下の2つです
- service.py
- server.py
service.py
import os
import win32service
import win32serviceutil
import win32event
import logging
import servicemanager
import socket
import datetime
from socketserver import ThreadingTCPServer
import server
logging.basicConfig(
filename=ログ出力先,
level=logging.DEBUG,
format="%(asctime)s:LINE[%(lineno)s] %(levelname)s %(message)s"
)
class PythonService(win32serviceutil.ServiceFramework):
_svc_name_ = 'SocketServer Test'
_svc_display_name_ = 'SocketServer Test'
_svc_description_ = 'SocketServer Test description'
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
self.stop_event = win32event.CreateEvent(None, 0, 0, None)
socket.setdefaulttimeout(60)
self.stop_requested = False
ipaddr = 'IPアドレス'
port = ポート番号
address = (ipaddr, int(port))
sockserver = ThreadingTCPServer(address, server.EchoHandler)
self.sockserver = sockserver
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.stop_event)
self.stop_requested = True
self.sockserver.shutdown()
def SvcDoRun(self):
servicemanager.LogMsg(
servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_, '')
)
self.main()
def main(self):
while True:
if self.stop_requested:
break
try:
ThreadingTCPServer.allow_reuse_address = True
self.sockserver.serve_forever()
except Exception as e:
logging.error(str(type(e)))
logging.error(str(e.args))
logging.error(str(e))
if __name__ == '__main__':
win32serviceutil.HandleCommandLine(PythonService)
server.py
from socketserver import BaseRequestHandler
import logging
import datetime
import os
logging.basicConfig(
filename=ログ出力先,
level=logging.DEBUG,
format="%(asctime)s:LINE[%(lineno)s] %(levelname)s %(message)s"
)
class EchoHandler(BaseRequestHandler):
def handle(self):
try:
message = self.request.recv(1024)
logging.info(message)
self.request.sendall(message)
except Exception as e:
logging.error(str(type(e)))
logging.error(str(e.args))
logging.error(str(e))
注意点
- 上記の2ファイルは同じフォルダ内に配置しましょう
- serve_forever()したsocketserverはサービス停止時に必ずshutdownさせる処理を書きましょう。これをしないとサービスを停止できず、削除も出来なくなります
サービス登録
配置したpythonファイルのフォルダに移動し以下のコマンドを実行します
# サービス登録
python service.py install
# サービス開始
python service.py start
[スタート]⇒[Windows 管理ツール]⇒[サービス]で登録されていることを確認しましょう
Discussion