Mar-24-2019, 08:29 PM
The following code shows the name of a new inserted USB stick in a PyQt5 GUI on Linux. Unfortunately, a pyudev.device._errors.DeviceNotFoundAtPathError appears in console as soon as you unplug the USB stick without properly ejecting it.
What need to be changed to fix this error?
main.py:
What need to be changed to fix this error?
main.py:
from functools import partial import os import sys import pyudev from PyQt5.QtWidgets import QApplication, QMainWindow from PyQt5.uic import loadUi from PyQt5.QtCore import QSocketNotifier, QObject, pyqtSignal class MainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) loadUi("mainwindow.ui", self) def update_path(self, name): self.label_usb_mass_storage_url.setText(str(name)) class LinuxDeviceMonitor(QObject): devices_changed = pyqtSignal(list) def __init__(self): super().__init__() self._context = pyudev.Context() self._monitor = pyudev.Monitor.from_netlink(self._context) self._monitor.start() self._devices = set() self._process_devices(self._context.list_devices(), action="add") def fileno(self): return self._monitor.fileno() # return file descriptor @property def device_names(self): if self._devices: return [pyudev.Devices.from_path(self._context, device).get("DEVNAME") for device in self._devices] else: return ["No USB mass storage"] def process_incoming(self): read_device = partial(pyudev._util.eintr_retry_call, self._monitor.poll, timeout=0) self._process_devices(iter(read_device, None)) self.devices_changed.emit(self.device_names) def _process_devices(self, devices, action=None): for device in devices: action = device.action if action is None else action if action in ("add", "change") and self._is_usb_mass_storage_device(device): self._devices.add(device.sys_path) elif action == "remove" and device.sys_path in self._devices: self._devices.remove(device.sys_path) @classmethod def _read_device_flag(self, device, name): path = os.path.join(device.sys_path, name) try: with open(path) as data: return bool(int(data.read())) except (IOError, ValueError): return False def _is_usb_mass_storage_device(self, device): is_removable = self._read_device_flag(device, "removable") has_size = self._read_device_flag(device, "size") has_usb = device.get("ID_BUS") == "usb" has_no_disc = device.get("ID_CDROM") is None return is_removable and has_size and has_usb and has_no_disc def main(): app = QApplication(sys.argv) main_window = MainWindow() main_window.show() linux_device_monitor = LinuxDeviceMonitor() notifier = QSocketNotifier(linux_device_monitor.fileno(), QSocketNotifier.Read) notifier.activated.connect(linux_device_monitor.process_incoming) linux_device_monitor.devices_changed.connect(main_window.update_path) sys.exit(app.exec_()) if __name__ == '__main__': main()mainwindow.ui:
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>MainWindow</class> <widget class="QMainWindow" name="MainWindow"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>500</width> <height>250</height> </rect> </property> <property name="windowTitle"> <string>MainWindow</string> </property> <widget class="QWidget" name="centralwidget"> <layout class="QGridLayout" name="gridLayout"> <item row="0" column="0"> <widget class="QLabel" name="label_path_to_mass_storage"> <property name="locale"> <locale language="English" country="UnitedKingdom"/> </property> <property name="text"> <string>USB mass storage:</string> </property> </widget> </item> <item row="0" column="1"> <widget class="QLabel" name="label_usb_mass_storage_url"> <property name="text"> <string/> </property> </widget> </item> </layout> </widget> <widget class="QMenuBar" name="menubar"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>500</width> <height>28</height> </rect> </property> </widget> <widget class="QStatusBar" name="statusbar"/> </widget> <resources/> <connections/> </ui>