单实例应用程序 - 传递命令

时间:2011-04-02 02:06:43

标签: python wxpython single-instance

我正在使用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 个答案:

答案 0 :(得分:2)

“单一实例”应用程序有两个部分。

“客户端”,双击并开始运行。如果服务器未运行,则启动服务器。它将命令传递给服务器。然后停下来。让服务器继续运行。

“服务器”,由每个客户端启动。它执行“侦听已定义的端口”。或者也许从一个命名管道中读取(有时候效果更好)。

服务器完成实际工作。客户端将命令传递给它。

答案 1 :(得分: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

所以我抓住了它的位置并阅读,这几乎是因为我的愚蠢,希望这可能对某些人有所帮助。