如何让两个程序互相通信

2024-04-24 09:01:04 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在研究python中的网络和多线程。我已经看过了同期期货和SocketServer,并尝试在我正在处理的示例中使用这些。文档中的示例看起来足够简洁,但是很难将它们应用到我正在研究的示例中。在

示例如下。2个GUI应用程序,一个通过用户交互向另一个发送信息,另一个显示此信息。在

到目前为止,我已经启动并运行了两个应用程序。应用程序A的服务器在一个单独的线程中运行。应用程序B能够连接到服务器并发送所需的信息。在

在这一点上,我似乎找不到一个好的方法来获得显示在应用程序a的GUI中的信息。我可以想出几种简单的方法来实现这一点,但我对最好的/最具python风格的方式感兴趣。这似乎是一个常见的问题,所以这里必须有一个通用的模式来使用。所以我的问题是。在

  • 当服务器运行时,如何从自定义请求处理程序获取信息到服务器。在
  • 如何在主应用程序运行时从线程获取信息?在

示例代码如下

服务器窗口

import SocketServer
import concurrent.futures
import sys
from PyQt4 import QtGui

HOST = 'localhost'
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST, PORT)


class MyRequestHandler(SocketServer.StreamRequestHandler):
    def handle(self):
        print('...connected from:', self.client_address)        
        data = self.rfile.readline().strip()
        print('Data from client %s' % data)

class ServerWindow(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.setGeometry(1500, 100, 500, 500)

        self._control = QtGui.QWidget()
        self.setCentralWidget(self._control)

        l = QtGui.QVBoxLayout(self._control)
        t = QtGui.QTextEdit()
        l.addWidget(t)

        self.executor = concurrent.futures.ThreadPoolExecutor(max_workers=1)
        self.startServerThread()

        self.show()

    def startServerThread(self):
        self.executor.submit(self.startServer)

        # How to get information from the thread while it is still running?

    def startServer(self):
        print('starting server')
        tcpServ = SocketServer.TCPServer(ADDR, MyRequestHandler)
        print('waiting for connection...')
        tcpServ.serve_forever()

        # How to get information from the client (custom request handler)
        # back to the GUI in a thread safe manner?

def launch():
    app = QtGui.QApplication(sys.argv)
    ex = ServerWindow()
    sys.exit(app.exec_())

if __name__ == '__main__':
    launch()

客户端窗口

^{pr2}$

Tags: fromimportself服务器client信息应用程序示例
2条回答

While the server is running, how to get the information from the custom request handler to the server.

how to get information from the thread to the main application while it is running?

这些是我对它应该如何运作的想法。在

class MyRequestHandler(SocketServer.StreamRequestHandler):
    @property
    def application_window(self):
        # you would override setup() for this, usually.
        return self.server.application_window

    def handle(self):
        print(self.application_window)

# ...

    def startServer(self):
        print('starting server')
        tcpServ = SocketServer.TCPServer(ADDR, MyRequestHandler)
        tcpServ.application_window = self # !!!!!!!!!!!!!!!!!!!!!!!!! added
        print('waiting for connection...', self)
        tcpServ.serve_forever()

也许你需要调整一下。顺便说一下,sharing information between server and client有一些技巧。在

因此,我知道的将数据从线程传输到应用程序主GUI线程的少数几种方法之一是将数据放入python Queue。这个QueueQThread(一个支持Qt信号和插槽的Qt线程实现)读取。QThreadqueue.get()进行阻塞调用。当您的handle()方法将数据放入Queue中时,QThread将解除阻塞,从队列中读取数据,并向GUI线程发出线程安全信号。作为演示,我将数据添加到QTextEdit。在

因此,基本上您需要在python线程和Qt GUI之间建立一个中介,Qt GUI通常通过信号/插槽进行交互。QThread执行此任务,将线程安全的Queue对象与线程安全qt信号发射链接起来。在

这实际上遵循了我给出的here的类似答案,但是这里有一个套接字,而不是一个将数据放入队列的自定义线程。在

您可能还对thissopost感兴趣,这解释了我用来生成QThread和连接信号等的一些代码行是按顺序编写的!在

当应用程序窗口关闭时,我添加了一行代码来关闭socket服务器(用于后台继续运行的socket服务器)

服务器窗口代码

import SocketServer
import concurrent.futures
import sys
from PyQt4 import QtGui
from PyQt4 import QtCore
from Queue import Queue

HOST = 'localhost'
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST, PORT)

# create a global queue object that both the handle() method and the QThread (see later in the code) can access
queue = Queue()

class MyRequestHandler(SocketServer.StreamRequestHandler):
    def handle(self):
        print('...connected from:', self.client_address)        
        data = self.rfile.readline().strip()
        print('Data from client %s' % data)
        queue.put(data)

class ServerWindow(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.setGeometry(1500, 100, 500, 500)

        self._control = QtGui.QWidget()
        self.setCentralWidget(self._control)

        l = QtGui.QVBoxLayout(self._control)
        self.t = QtGui.QTextEdit()
        l.addWidget(self.t)

        self.executor = futures.ThreadPoolExecutor(max_workers=1)
        self.startServerThread()

        self.show()

    @QtCore.pyqtSlot(str)
    def receive_data(self, data):
        self.t.moveCursor(QtGui.QTextCursor.End)
        self.t.insertPlainText( data )

    def startServerThread(self):
        self.executor.submit(self.startServer)

        # How to get information from the thread while it is still running?

    def startServer(self):
        print('starting server')
        self.tcpServ = SocketServer.TCPServer(ADDR, MyRequestHandler)
        print('waiting for connection...')
        self.tcpServ.serve_forever()

        # How to get information from the client (custom request handler)
        # back to the GUI in a thread safe manner?

# This class runs in a QThread and listens on the end of a queue and emits a signal to the GUI
class MyReceiver(QtCore.QObject):
    mysignal = QtCore.pyqtSignal(str)

    def __init__(self,queue,*args,**kwargs):
        QtCore.QObject.__init__(self,*args,**kwargs)
        self.queue = queue

    @QtCore.pyqtSlot()
    def run(self):
        while True:
            text = self.queue.get()
            self.mysignal.emit(text)


def launch():
    app = QtGui.QApplication(sys.argv)

    ex = ServerWindow()

    # Create thread that will listen on the other end of the queue, and send the text to the textedit in our application
    thread = QtCore.QThread()
    my_receiver = MyReceiver(queue)
    my_receiver.mysignal.connect(ex.receive_data)
    my_receiver.moveToThread(thread)
    thread.started.connect(my_receiver.run)
    thread.start()

    ret_code = app.exec_()
    ex.tcpServ.shutdown()
    sys.exit(ret_code)

if __name__ == '__main__':
    launch()

相关问题 更多 >