python-3.xuser-interfacepyqt5pyudev

Using pyudev.pyqt5 within PyQt5's event loop


I wanted to write a small application that will display usb device's name in a small text browser, when it has been inserted. I am using pyudev to do that. Instead of using pyudev's own event loop, i found out that we can integrate pyudev into qt's event loop, by using MonitorObserver. I have been trying to do that, but the results are unfruitful. Here is the code that i have tried so far. Please tell me if i am making a mistake.

Imports

from PyQt5.QtCore import pyqtSignal,pyqtSlot,QObject,QSocketNotifier
from PyQt5.QtWidgets import QWidget,QApplication
from form_designer import Ui_Form
from pyudev.pyqt5 import MonitorObserver
from pyudev import Context,Monitor
from PyQt5 import QtCore

Small Class

class mainWindow(QWidget,Ui_Form):
    def __init__(self,monitor):
        super().__init__()

        self.setupUi(self)
        print("First test")

        monitor.filter_by(subsystem='tty')
        self.observer = MonitorObserver(monitor)
        print("second test")

        self.observer.deviceEvent.connect(self.device_connected)
    @pyqtSlot()
    def device_connected(self,device):
        self.textBrowser.append(device.sys_name)
        print("Test")

I even tested using prints to see how far the loop was going. Here is the initialization and main

def main():
    import sys
    app = QApplication(sys.argv)
    context = Context()
    monitor = Monitor.from_netlink(context)
    window = mainWindow(monitor)
    window.show()

    app.exec_()
    monitor.start()
if __name__ == '__main__':
    main()

When executed, it prints the first two prints and the slot never gets called.

FYI : Its been a week since i started learning python.


Solution

  • You need to start the monitor before starting the event-loop. Also, avoid using the @pyqtSlot decorator - it's rarely needed, and it's very easy to get the definition wrong if you don't know what you're doing (as you did in your example).

    So your code should look like this:

    class mainWindow(QWidget, Ui_Form):
        def __init__(self):
            ...
            context = Context()
            monitor = Monitor.from_netlink(context)
            monitor.filter_by(subsystem='tty')
            self.observer = MonitorObserver(monitor)
            self.observer.deviceEvent.connect(self.device_connected)
            monitor.start()
    
        def device_connected(self, device):
            self.textBrowser.append(device.sys_name)
            print("Test")
    
    def main():
        import sys
        app = QApplication(sys.argv)
        window = mainWindow()
        window.show()
        app.exec_()
    

    PS: it might be a good idea to comment out the filter_by line and plug in a usb device just to make sure everything is working okay.