あいさつ
つかさです。今回は、実行中のプログラムへの引数の送り方です。
メインウィンドウの文字列を与えられた引数に置き換えます。
例えば、既にランチャが起動しているときに
D:\bin\homuLauncher\htest2.py H:\howm2\Python
とすれば実行中のウィンドウがこんな感じになるようにします。
hlnch02.py
# -*- encoding: utf-8 -*- import wx,subprocess,os,sys,SocketServer,socket,threading class MyTxtCtr(wx.PySimpleApp): def OnInit(self): HOST, PORT = socket.gethostname(), 61955 argvs = sys.argv instance_name = u"%s-%s" % (self.GetAppName(), wx.GetUserId()) self.instance = wx.SingleInstanceChecker(instance_name) if self.instance.IsAnotherRunning(): if len(argvs) >= 2: self.client(HOST, PORT, argvs) wx.Exit() else: server = self.start_server(HOST, PORT) self.Frm = wx.Frame(None, -1, "homuLauncher", size=(400,60),pos=(400,400)) self.TxtCtr = wx.TextCtrl(self.Frm, -1) self.Frm.Show() return 1 def start_server(self,host, port): server = ThreadedTCPServer((host, port), ThreadedTCPRequestHandler) ip, port = server.server_address server_thread = threading.Thread(target=server.serve_forever) server_thread.setDaemon(True) server_thread.start() def client(self,ip, port, arg): message = os.path.abspath(' '.join(arg[1:])) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((ip, port)) sock.send(message) response = sock.recv(1024) # print "Received: %s" % response sock.close() class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler): def handle(self): data = self.request.recv(1024) wx.GetApp().TxtCtr.SetValue(data) response = 'string length: %d' % len(data) # print 'responding to',data,'with',response self.request.send(response) class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): pass app = MyTxtCtr() app.MainLoop()
説明
- 初回起動時に、本体と共にバックグラウンドでサーバーを起動する。そのサーバーが何かメッセージを受け取れば、それに応じて本体に反映させるようにしておく
- 二度目の起動時には、そのサーバーに接続するクライアントを作成。引数を渡し、自身は終了する
という構造です。
ポート番号を予め指定し、サーバーとクライアントを作ることで、初回起動時のプログラムと二度目以降のとをつなげるという仕組みらしい。もっと簡単にできると思ってたけどわりと大掛かりなんですね。それとも他の方法があるのかしらん。
解説
二重起動のチェック
if self.instance.IsAnotherRunning(): if len(argvs) >= 2: self.client(HOST, PORT, argvs) wx.Exit() else: server = self.start_server(HOST, PORT)
wx.SingleInstanceCheckerで、既に起動中のプログラムがあるかどうかで分岐。
- 初回起動なら サーバーをバックグラウンドで起動する
- 既に起動しているなら クライアントを作成して、既に起動中のプログラムのサーバーに接続する
という具合です。それぞれstart_serverとclientで行ってます。
サーバー側
def start_server(self,host, port): server = ThreadedTCPServer((host, port), ThreadedTCPRequestHandler) ip, port = server.server_address server_thread = threading.Thread(target=server.serve_forever) server_thread.setDaemon(True) server_thread.start()
ここでサーバーを動かしてるわけですが、二つのクラスを利用してます。
1 ThreadedTCPRequestHandlerクラス
クライアントからメッセージを受け取った時の処理をThreadedTCPRequestHandlerクラスで定めます。
class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler): def handle(self): data = self.request.recv(1024) wx.GetApp().TxtCtr.SetValue(data) #Note to the self.server.app response = 'string length: %d' % len(data) # print 'responding to',data,'with',response self.request.send(response)
受け取ったデータを、SetValueでテキストボックスに貼り付けてますね。
2 ThreadedTCPServerクラス
class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): pass
非同期的な動作をサポートするのにこれが必要らしい。参考にしたのがこうしてたのでとりあえずこうしてます。
クライアント側
def client(self,ip, port, arg): message = os.path.abspath(' '.join(arg[1:])) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((ip, port)) sock.send(message) response = sock.recv(1024) # print "Received: %s" % response sock.close()
- ソケットを作成
- サーバーに接続
- コマンドライン引数をサーバーに送る
- レスポンスを受け取り
- 終了
という順序ですね。
0 件のコメント:
コメントを投稿