Приложение для одного экземпляра - передача команд

Я использую 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" состоит из двух частей.

"Клиент", который дважды щелкает и запускается. Если сервер не работает, он запускает сервер. Он передает команды на сервер. И останавливается. Оставив сервер работающим.

"Сервер", который запускается каждым клиентом. Это делает "прослушивание определенного порта". Или, возможно, чтение из именованного канала (который иногда срабатывает лучше).

Сервер делает реальную работу. Клиент передает ему команды.

Другие вопросы по тегам