from PyQt5.QtCore import QSharedMemory, QTimer, QObject, pyqtSignal
from PyQt5.QtWidgets import QMessageBox, QWidget, QApplication
class SingleInstanceException(Exception):
pass
class SharedMemoryReader(QObject):
received = pyqtSignal(bytes)
def __init__(self, key, parent = None):
super().__init__(parent)
memory = QSharedMemory(key)
if not memory.create(1, QSharedMemory.ReadWrite):
raise SingleInstanceException()
self._memory = memory
memory.lock()
self.clearMemory()
memory.unlock()
# timer to poll shared memory for changes
timer = QTimer()
timer.timeout.connect(self.onTimeOut)
timer.start(500)
self._timer = timer
def clearMemory(self):
self._memory.data()[0] = b'0'
def onTimeOut(self):
memory = self._memory
memory.lock()
data = memory.data()[0]
if data != b'0':
self.received.emit(data)
self.clearMemory()
memory.unlock()
class SharedMemoryWriter(QObject):
def __init__(self, key, parent = None):
super().__init__(parent)
memory = QSharedMemory(key)
self._memory = memory
def write(self, message):
memory = self._memory
if not memory.isAttached():
memory.attach()
memory.lock()
memory.data()[0] = message
memory.unlock()
if __name__ == "__main__":
app = QApplication([])
# guid to identify your application (some unique string)
guid = "5c197822-e86a-4547-a4f1-dbb5087b962d"
widget = QWidget()
try:
# First instance creates shared memory.
# If memory exists exception raised and it means that it's not first instance.
reader = SharedMemoryReader(guid)
reader.received.connect(lambda: QMessageBox.information(widget,"","Signal from another instance received"))
except SingleInstanceException:
# Second instance writes to memory (sends signal to first instance) and exits
writer = SharedMemoryWriter(guid)
writer.write(b'1')
exit(0)
# No exception raised - that means its first instance of application
# Continue normally
widget.show()
app.exec_()