Frage

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:

  • start netcat -u -l -p 7777
  • start the application
  • click on the button (netcat will write 'hello'
  • type something into the netcat console and hit enter
  • -> the app crashes

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.

War es hilfreich?

Lösung

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()
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top