i'm developping a network application in python, that features zeroconf/avahi, bidirectional UDP-connection and a Qt-interface. for my bi-directional communication i have written a small class that connects to a remote server via UDP and keeps listening on that socket, in case the server wants to talk back.
what i really want is, that my network component has an asynchronous receiver, which just runs and emits messages as they arrive from the peer.
originally i used SocketServer
for this task, but i soon discovered, that the SocketServer
would stop calling my RequestHandler
once i start running the main loop of the GUI.
so i researched a bit and found this, which i adapted to my needs.
unfortunately, my application now segfaults as soon as data arrives from the server.
here's a little example program that exposes the problem:
import sys
import gobject
import socket
from PySide.QtCore import *
from PySide.QtGui import *
def callback(socket, *args):
data, address = socket.recvfrom(8192)
print "data arrived", data
return True
class Client:
def __init__(self, host, port):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.remote = (host, port)
gobject.io_add_watch(self.socket, gobject.IO_IN, callback)
def send(self, data=[]):
self.socket.sendto( data, self.remote)
class Form(QDialog):
def __init__(self, parent=None):
super(Form, self).__init__(parent)
# widget
self.button = QPushButton("Hello World")
self.button.clicked.connect(self.sayHello)
layout = QVBoxLayout()
layout.addWidget(self.button)
self.setLayout(layout)
self.connection = Client('localhost', 7777)
def sayHello(self):
self.connection.send('hello')
if __name__ == '__main__':
app = QApplication(sys.argv)
form = Form()
form.show()
sys.exit(app.exec_())
i'm using it like this:
netcat -u -l -p 7777
now i guess that the problem is, that i'm mixing glib and qt, which both provide similar functionality (in terms of mainloop), and the gobject.io_add_watch
depends on a running glib-mainloop, but instead there's a Qt mainloop.
what's the proper way to get an asynchronous receiving UDP-client within the PySide/Qt framework? if possible, i'd like to avoid my network code to depend on Qt/PySide, as i want to reuse it on an embedded headless system (beaglebone), and Qt seems to be a bit of an overkill here.
seems like the problem is rather simple: when using non threads with gobject
, one has to initialize them explicitely.
adding the following at the beginning of the 'main' function solves the issue:
gobject.threads_init()