On Wed, Nov 3, 2010 at 10:46 AM, Hans-Peter Jansen <[email protected]> wrote:
> Hi Phil et al.,
>
> now, that sip.voidptr allows to access and modify shared memory
> segments, here are Qt4's ipc examples converted to PyQt, tested with
> Python 2.6. Testing with 2.7 and 3.x might be a good idea..
>
> Note, that you need at least sip4 852:af2d7120dd7f for the sharedmemory
> example.
>
Thanks for porting the example :)
I have attached some ipc code I wrote once which uses QLocalServer.
Maybe someone finds it useful.

Henning
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os
import pickle
import atexit
import urllib
import tempfile

from PyQt4.QtCore import QSharedMemory, SIGNAL, QIODevice, QObject
from PyQt4.QtNetwork import QLocalServer, QLocalSocket
from PyQt4.QtGui import QApplication, QPushButton


class IpcBase(QObject):

    timeout = 1000


    class Error(Exception):
        pass


    def __init__(self, channel=None, parent=None):
        QObject.__init__(self, parent)
        self.socket_filename = os.path.expanduser("~/.ipc_%s" % self.generate_unique_id(channel))
        print self.socket_filename
        self.shared_mem = QSharedMemory()
        self.shared_mem.setKey(self.socket_filename)
        if self.shared_mem.attach():
            self.is_running = True
        else:
            self.is_running = False
            

    def generate_unique_id(self, channel=None):
        if channel is None:
            channel = os.path.basename(sys.argv[0])

        return "%...@%s" % (
           channel,
           os.environ.get("DISPLAY", "-1")
           )



class IpcServer(IpcBase):


    def __init__(self, channel):
        IpcBase.__init__(self, channel)
        if self.is_running:
            raise self.Error("IPC server already running")
        if not self.shared_mem.create(1):
            print >>sys.stderr, "Unable to create single instance"
            return
        self.server = QLocalServer(self)
        self.connect(self.server, SIGNAL("newConnection()"),
               self.receive_message)
        if os.path.exists(self.socket_filename):
            os.remove(self.socket_filename)
        self.server.listen(self.socket_filename)
        atexit.register(self.cleanup)


    def cleanup(self):
        os.remove(self.socket_filename)

            
    def receive_message(self):
        socket = self.server.nextPendingConnection()
        if not socket.waitForReadyRead(self.timeout):
            print >>sys.stderr, socket.errorString()
            return
        byte_array = socket.readAll()
        self.handle_new_message(pickle.loads(str(byte_array)))


    def handle_new_message(self, message):
        raise NotImplementedError, self.handle_new_message



class IpcClient(IpcBase):


    def __init__(self, channel):
        IpcBase.__init__(self, channel)
        if not self.is_running:
            raise self.Error("Client cannot connect to IPC server. Not running.")


    def send_message(self, message):
        if not self.is_running:
            raise self.Error("Client cannot connect to IPC server. Not running.")
        socket = QLocalSocket(self)
        socket.connectToServer(self.socket_filename, QIODevice.WriteOnly)
        if not socket.waitForConnected(self.timeout):
            raise self.Error(str(socket.errorString()))
        socket.write(pickle.dumps(message))
        if not socket.waitForBytesWritten(self.timeout):
            raise self.Error(str(socket.errorString()))
        socket.disconnectFromServer()






class SingleApplicationDemo(QApplication):

    
    def __init__(self, argv=None, application_id=None):
        if argv is None:
            argv = sys.argv
        QApplication.__init__(self, argv)
        self.ipc_server = None
        self.ipc_client = None
        try:
            ipc = self.ipc_client = IpcClient(application_id)
            self.send_message = ipc.send_message
        except IpcClient.Error:
            ipc = self.ipc_server = IpcServer(application_id)
            ipc.handle_new_message = self.handle_new_message 
            print "Running as server, waiting for input"
        self.is_running = ipc.is_running


    def handle_new_message(self, message):
        print "Received:", message

    
           
if __name__ == "__main__":
    app = SingleApplicationDemo()
    if app.is_running:
        app.send_message(sys.argv)
    else:
        win = QPushButton()
        win.setText("Close")
        win.clicked.connect(win.close)
        win.show()
        app.exec_()
_______________________________________________
PyQt mailing list    [email protected]
http://www.riverbankcomputing.com/mailman/listinfo/pyqt

Reply via email to