I am dipping my toes into networking and multithreading in python. I have gone through the docs on concurrent.futures and SocketServer and am attempting to use these in the example I am working on. The examples in the docs seem strait forward enough but am struggling to apply them to the example I am working on.
The example is as follows. 2 GUI applications, one that sends information to the other via user interaction and the other displays this information.
So far I have the 2 applications up and running. Application A has the server running in a separate thread. Application B is able to connect to the server and send the desired information.
At this point I cannot seem to find a nice way to get the information displayed in the GUI of application A. I can think of several hacky ways of doing it but am interested in the nicest / most pythonic way. This seems a common problem so there must be a common pattern to use here. So my questions are.
- 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?
Example code is as follows
Server Window
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()
Client Window
import socket
import sys
import functools
from PyQt4 import QtGui
HOST = 'localhost'
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST, PORT)
class ClientWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.setGeometry(1500, 650, 500, 500)
self._control = QtGui.QWidget()
self.setCentralWidget(self._control)
l = QtGui.QVBoxLayout(self._control)
for i in range(5):
name = 'test %d' % i
b = QtGui.QPushButton(name)
l.addWidget(b)
b.pressed.connect(functools.partial(self.onButtonClick, name))
self.show()
def onButtonClick(self, buttonName):
print('connecting to server')
tcpCliSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpCliSock.connect(ADDR)
print('Sending name %s' % buttonName)
tcpCliSock.send(buttonName)
tcpCliSock.close()
def launch():
app = QtGui.QApplication(sys.argv)
ex = ClientWindow()
sys.exit(app.exec_())
if __name__ == '__main__':
launch()