在Python3中定义与pyudev/evdev兼容的文件描述符
Hey there! Let’s work through that Bluetooth button issue you’re facing. You’ve got connection detection working, but button presses aren’t registering—and you’re right to suspect the evdev file descriptor setup for select is the culprit. Here’s how to troubleshoot and fix this:
First, Rule Out System-Level Issues
Before diving into code, let’s make sure the hardware and OS are behaving:
Check the evdev node & test events manually
After connecting your Bluetooth button, run these commands:# List all input devices ls /dev/input/event* # Install evtest if you haven't already sudo apt install evtest # Test each event node until you find your button sudo evtest /dev/input/eventXIf
evtestcan pick up button presses, the problem is in your code. If not, re-pair the button or check Bluetooth logs withdmesg | grep Bluetoothfor errors.Fix permissions
Regular users often don’t have access to/dev/inputnodes. Either run your script withsudo, or add your user to theinputgroup (requires a reboot to take effect):sudo usermod -aG input $USER
Adjust Your evdev & select Logic
Your pyudev setup for connection detection is a good start, but we need to properly grab the evdev device’s file descriptor and use it with select. Here’s a revised code snippet with key fixes:
import functools import pyudev import evdev from select import select def handle_key_presses(device): """Process incoming key events from the Bluetooth button""" for event in device.read_loop(): if event.type == evdev.ecodes.EV_KEY: key_data = evdev.categorize(event) # Print key state (pressed/released) status = "pressed" if key_data.keystate == key_data.key_down else "released" print(f"Button {key_data.keycode}: {status}") def on_button_connected(context, device): """Triggered when the Bluetooth button connects""" # Target only input event devices (Bluetooth buttons are HID input devices) if device.subsystem == "input" and device.device_type == "event": try: # Create an evdev device object from the node path btn_device = evdev.InputDevice(device.device_node) print(f"Connected to button: {btn_device.name}") # Use select to listen for events on the device's file descriptor while True: # Listen for readable events (button presses trigger this) readable, _, _ = select([btn_device.fd], [], []) if btn_device.fd in readable: handle_key_presses(btn_device) except Exception as err: print(f"Error handling device: {str(err)}") # Set up pyudev to monitor input device connections context = pyudev.Context() monitor = pyudev.Monitor.from_netlink(context) monitor.filter_by(subsystem="input") # Start monitoring for new devices observer = pyudev.MonitorObserver(monitor, callback=functools.partial(on_button_connected, context)) observer.start() # Keep the script running try: while True: pass except KeyboardInterrupt: print("\nStopping monitor...") observer.stop()
Key Fixes Explained:
- Proper evdev Device Initialization: We use
device.device_node(from pyudev) to create anevdev.InputDevice—this gives us a valid file descriptor viabtn_device.fdthat works withselect. - Select Listening: We pass the device’s fd to
selectand wait for it to become readable (which happens when a button is pressed/released). - Event Filtering: We only process
EV_KEYevents to ignore irrelevant input data.
Extra Checks If It Still Fails
- Update your Python packages to the latest versions:
pip install --upgrade pyudev evdev - Verify your Bluetooth button uses a standard HID profile—some custom buttons may require additional driver setup.
- Check system logs with
journalctl -u bluetooth.servicefor connection-related errors.
内容的提问来源于stack exchange,提问作者Pôm'

