Приложение для одного экземпляра - передача команд
Я использую wxPython и пытаюсь создать приложение для одного экземпляра. Что касается этого, нет проблем. Моя проблема заключается в передаче команд в уже существующий экземпляр.
Итак, допустим, что когда я дважды щелкаю файл, связанный с моим приложением, он читает файл и отображает, вот пример:
import wx
import sys
import os
import SocketServer
import socket
import threading
class MyFrame(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, wx.Size(320, 350))
getfile = os.path.abspath(sys.argv[1])
print getfile
fopen = open (getfile, 'r')
fread = fopen.read()
panel = wx.Panel(self, -1)
wx.StaticText(panel, -1, fread, (45, 25), style=wx.ALIGN_CENTRE)
self.Centre()
class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):
def handle(self):
data = self.request.recv(1024)
cur_thread = threading.currentThread()
# do something with the request
print "work"
# could instead of the length of the input, could return error codes, more
# information (if the request was a query), etc. Using a length function
# as a simple example
response = 'string length: %d' % len(data)
print 'responding to',data,'with',response
self.request.send(response)
class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
stopped = False
allow_reuse_address = True
def serve_forever(self):
while not self.stopped:
self.handle_request()
def force_stop(self):
self.server_close()
self.stopped = True
def client(ip, port, message):
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()
def start_server(host, port):
server = ThreadedTCPServer((host, port), ThreadedTCPRequestHandler)
ip, port = server.server_address
# Start a thread with the server -- that thread will then start one
# more thread for each request
server_thread = threading.Thread(target=server.serve_forever)
# Exit the server thread when the main thread terminates
server_thread.setDaemon(True)
server_thread.start()
return server
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, -1, 'test')
frame.Show(True)
self.SetTopWindow(frame)
return True
def main():
app = MyApp(0)
app.MainLoop()
if __name__ == '__main__':
HOST, PORT = socket.gethostname(), 61955
server = None
try:
client(HOST, PORT, ' '.join(sys.argv))
sys.exit()
except socket.error:
server = start_server(HOST, PORT)
main()
Это работает просто отлично, но теперь я хочу сделать приложение единичным. И я знаю, что есть несколько способов сделать это, и в моем случае я обнаружил, что прослушивание определенного порта, вероятно, лучший вариант. Но даже используя такую опцию, я понятия не имею, как передать информацию о файле или, по крайней мере, имя в исходный экземпляр и отобразить его.
Итак, приложение должно быть:
- Приложение единственного экземпляра.
- Он должен быть в состоянии прочитать файлы, дважды щелкнув по ним.
- Если экземпляр уже открыт, передайте информацию или имя файла исходному экземпляру, чтобы он мог автоматически обновлять и отображать данные файла.
Кроме того, я не включил никакого кода для прослушивания определенного порта, потому что я действительно не очень много знаю об этом, поэтому любая помощь по этому вопросу также очень ценится.
РЕДАКТИРОВАТЬ: Код отредактирован с "прослушиванием определенного порта", он взят из примера. Обратите внимание, что print "work"
отправляет в работающий экземпляр, я просто не знаю, как заставить его работать в моем случае (из-за моего простого невежества).
2 ответа
Это решение:
import wx
import sys
import os
import SocketServer
import socket
import threading
class MyFrame(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, wx.Size(320, 350))
getfile = os.path.abspath(sys.argv[1])
print getfile
fopen = open (getfile, 'r')
fread = fopen.read()
panel = wx.Panel(self, -1)
self.static = wx.StaticText(panel, -1, fread, (45, 25), style=wx.ALIGN_CENTRE)
self.Centre()
class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):
def handle(self):
data = self.request.recv(1024)
cur_thread = threading.currentThread()
data = data.split()
gfile = os.path.abspath(data[-1])
fopen = open(gfile, 'r')
fread = fopen.read()
self.server.app.static.SetLabel(fread)
#Note to the self.server.app
response = 'string length: %d' % len(data)
print 'responding to',data,'with',response
self.request.send(response)
class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
stopped = False
allow_reuse_address = True
def serve_forever(self):
while not self.stopped:
self.handle_request()
def force_stop(self):
self.server_close()
self.stopped = True
def client(ip, port, message):
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()
def start_server(host, port):
server = ThreadedTCPServer((host, port), ThreadedTCPRequestHandler)
ip, port = server.server_address
# Start a thread with the server -- that thread will then start one
# more thread for each request
server_thread = threading.Thread(target=server.serve_forever)
# Exit the server thread when the main thread terminates
server_thread.setDaemon(True)
server_thread.start()
return server
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, -1, 'test')
frame.Show(True)
server.app = frame
#Note the server.app
self.SetTopWindow(frame)
return True
def main():
app = MyApp(0)
app.MainLoop()
if __name__ == '__main__':
HOST, PORT = socket.gethostname(), 61955
server = None
try:
client(HOST, PORT, ' '.join(sys.argv))
sys.exit()
except socket.error:
server = start_server(HOST, PORT)
main()
По сути, мне пришлось связать server.app с моим фреймом:
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, -1, 'test')
frame.Show(True)
server.app = frame
#Note the server.app
Так что я мог позвонить позже:
data = self.request.recv(1024)
cur_thread = threading.currentThread()
data = data.split()
gfile = os.path.abspath(data[-1])
fopen = open(gfile, 'r')
fread = fopen.read()
self.server.app.static.SetLabel(fread)
Важным здесь является self.server.app, хотя я хотел передать команды запущенному экземпляру. И data
делает это для меня. Допустим, я открываю уже открытое приложение с файлом test.app, тогда значение данных будет:
\pathtoyourapplication\application.py test.app
Так что я схватил его местонахождение и прочитал, и это в значительной степени это из-за моей глупости, надеюсь, это может быть полезно для кого-то, в некотором роде.
Приложение "Single Instance" состоит из двух частей.
"Клиент", который дважды щелкает и запускается. Если сервер не работает, он запускает сервер. Он передает команды на сервер. И останавливается. Оставив сервер работающим.
"Сервер", который запускается каждым клиентом. Это делает "прослушивание определенного порта". Или, возможно, чтение из именованного канала (который иногда срабатывает лучше).
Сервер делает реальную работу. Клиент передает ему команды.