@sparrow: Danke für den vielen Code. Momentan bin ich allerdings mit dem Code von __deets__ für Linux noch vollkommen ausgelastet.
Bei der Erkennung von USB-Speichern konnte ich mein DVD-Laufwerk mittlerweile erfolgreich ausschließen. Ich habe noch etwas weiter an den Ausschlusskriterien geschraubt, damit auch per USB angeschlossene, externe DVD-Laufwerke nicht berücksichtigt werden.
Mittels `QSocketNotifier` konnte ich dann tatsächlich ein Signal auslösen, wenn ein USB-Stick an- oder abgesteckt wird. Allerdings ist da noch
einiges im Argen. Der `QSocketNotifier` ist wohl nicht ganz korrekt eingebunden.
- USB-Stick bei Programmstart nicht angesteckt:
- Wenn man ohne angestecktem USB-Stick das Programm startet, wird auf der Qt-Oberfläche ganz korrekt kein Pfad angezeigt.
- Steckt man den USB-Stick ein, während das Programm läuft, wird `[]` angezeigt. Anscheinend ist die Erkennung des USB-Sticks nicht schnell genug und es wird eine leere Liste zurückgegeben.
- Wenn man den USB-Stick wieder entfernt hat, wird weiterhin `[]` angezeigt.
- USB-Stick bei Programmstart angesteckt:
- Mit angestecktem USB-Start beim Programmstart wird kein Pfad auf der Qt-Oberfläche angezeigt.
- Erst sobald man den USB-Stick entfernt, erscheint der Pfad und die Fehlermeldung unten läuft in Endlosschleife in der Konsole.
- Steckt man den USB-Stick wieder ein, erscheinen in der Konsole keine Fehlermeldungen mehr.
Fehlermeldung:
Code: Alles auswählen
Traceback (most recent call last):
File "/home/ata/source/usb-detect/main.py", line 104, in <lambda>
notifier.activated.connect(lambda: main_window.update_path(str(linux_device_monitor.devices)))
File "/home/ata/source/usb-detect/main.py", line 50, in devices
return [pyudev.Devices.from_path(self._context, device).get("DEVNAME") for device in self._devices]
File "/home/ata/source/usb-detect/main.py", line 50, in <listcomp>
return [pyudev.Devices.from_path(self._context, device).get("DEVNAME") for device in self._devices]
File "/usr/lib/python3/dist-packages/pyudev/device/_device.py", line 83, in from_path
return cls.from_sys_path(context, path)
File "/usr/lib/python3/dist-packages/pyudev/device/_device.py", line 108, in from_sys_path
raise DeviceNotFoundAtPathError(sys_path)
pyudev.device._errors.DeviceNotFoundAtPathError: No device at '/sys/devices/pci0000:00/0000:00:14.0/usb1/1-6/1-6:1.0/host4/target4:0:0/4:0:0:0/block/sdb'
main.py:
Code: Alles auswählen
from functools import partial
import os
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.uic import loadUi
from PyQt5.QtCore import QSocketNotifier
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
loadUi("mainwindow.ui", self)
def update_path(self, path):
self.label_usb_mass_storage_url.setText(path)
class LinuxDeviceMonitor:
def __init__(self):
import pyudev
self._context = pyudev.Context()
self._monitor = pyudev.Monitor.from_netlink(self._context)
self._monitor.start()
self._devices = set()
self._listeners = []
self.rescan()
def rescan(self):
self._process_devices(
self._context.list_devices(),
action="add"
)
def add_listener(self, listener):
self._listeners.append(listener)
def remove_listener(self, listener):
self._listeners.remove(listener)
def fileno(self):
return self._monitor.fileno()
@property
def devices(self):
import pyudev
return [pyudev.Devices.from_path(self._context, device).get("DEVNAME") for device in self._devices]
def process_incoming(self, *_args):
from pyudev._util import eintr_retry_call
read_device = partial(eintr_retry_call, self._monitor.poll, timeout=0)
self._process_devices(iter(read_device, None))
def _process_devices(self, devices, action=None):
old = set(self._devices)
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 "remove" == action and device.sys_path in self._devices:
self._devices.remove(device.sys_path)
if self._devices != old:
devices = self.devices
for listener in self._listeners:
listener(devices)
def _is_usb_mass_storage_device(self, device):
def dev_path(device, name):
return "{}/{}".format(device.sys_path, name)
def removable(device):
removable_path = dev_path(device, "removable")
try:
return os.path.exists(removable_path) and int(open(removable_path).read())
except ValueError:
return False
def has_size(device):
size_path = dev_path(device, "size")
try:
return os.path.exists(size_path) and int(open(size_path).read())
except ValueError:
return False
def has_usb(device):
return device.get("ID_BUS") == "usb"
def has_no_disc(device):
return device.get("ID_CDROM") is None
return removable(device) and has_size(device) and has_usb(device) and has_no_disc(device)
def main():
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
linux_device_monitor = LinuxDeviceMonitor()
notifier = QSocketNotifier(linux_device_monitor.fileno(), QSocketNotifier.Read, linux_device_monitor.process_incoming())
notifier.activated.connect(lambda: main_window.update_path(str(linux_device_monitor.devices)))
sys.exit(app.exec_())
if __name__ == '__main__':
main()
mainwindow.ui:
Code: Alles auswählen
<?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="text">
<string>USB-Massenspeicher:</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>
Gruß
Atalanttore