如何使用Python通过Product ID和Vendor ID查找设备所连接的端口(如/dev/ttyACM0等)
Finding Serial Port Path by VID/PID in Python
Alright, let's figure out how to locate the serial port path (like /dev/ttyACM0) for a device using its Vendor ID (VID) and Product ID (PID) with Python. I'll walk you through two solid approaches—one using a handy library, and another that works without any extra installs.
Method 1: Using pyudev (Recommended)
The pyudev library is built specifically for interacting with Linux udev devices, so it's clean and reliable for this task.
First, install the library:
pip install pyudev
Then use this code snippet to find your device's port:
import pyudev def find_device_port(vid, pid): # Convert VID/PID to lowercase hex strings (handles both int and string inputs) vid_str = f"{vid:04x}" if isinstance(vid, int) else vid.lower() pid_str = f"{pid:04x}" if isinstance(pid, int) else pid.lower() context = pyudev.Context() # Iterate over all tty devices for device in context.list_devices(subsystem='tty'): # Find the parent USB device (where VID/PID are stored) usb_parent = device.find_parent('usb', 'usb_device') if usb_parent: # Match the VID/PID if (usb_parent.get('ID_VENDOR_ID') == vid_str and usb_parent.get('ID_MODEL_ID') == pid_str): return device.device_node # Returns path like /dev/ttyACM0 return None # Example usage: Replace with your device's VID and PID target_vid = 0x0483 # Can also pass as string "0483" target_pid = 0x5740 # Or string "5740" port = find_device_port(target_vid, target_pid) if port: print(f"Found your device at: {port}") else: print("Device not connected, or no matching port found.")
Method 2: Parsing sysfs (No Third-Party Libraries)
If you don't want to install extra packages, you can directly read from the Linux sysfs filesystem, which exposes device metadata.
import os def find_device_port(vid, pid): vid_str = f"{vid:04x}" if isinstance(vid, int) else vid.lower() pid_str = f"{pid:04x}" if isinstance(pid, int) else pid.lower() tty_class_path = '/sys/class/tty' for tty_device in os.listdir(tty_class_path): # Follow the symlink to the device's actual path device_symlink = os.path.join(tty_class_path, tty_device, 'device') if not os.path.exists(device_symlink): continue real_device_path = os.path.realpath(device_symlink) # Skip non-USB devices if 'usb' not in real_device_path: continue # Read VID and PID from sysfs files vid_file = os.path.join(real_device_path, 'idVendor') pid_file = os.path.join(real_device_path, 'idProduct') if not os.path.exists(vid_file) or not os.path.exists(pid_file): continue with open(vid_file, 'r') as f: current_vid = f.read().strip() with open(pid_file, 'r') as f: current_pid = f.read().strip() if current_vid == vid_str and current_pid == pid_str: return f"/dev/{tty_device}" return None # Example usage target_vid = 0x1a86 # CH340 VID target_pid = 0x7523 # CH340 PID port = find_device_port(target_vid, target_pid) print(port if port else "Device not found.")
Important Notes
- Permissions: Ensure your user has access to serial ports. On most Linux systems, add yourself to the
dialoutgroup with:
Log out and back in for this change to take effect.sudo usermod -aG dialout $USER - Duplicate Devices: If multiple devices share the same VID/PID, both methods will return the first matching port. To distinguish them, you can add checks for the device's serial number (look for
ID_SERIALin pyudev, or theserialfile in sysfs). - VID/PID Format: You can pass VID/PID as integers (e.g.,
0x1234) or lowercase hex strings (e.g.,"1234").
内容的提问来源于stack exchange,提问作者mekanizm
相关产品推荐
相关产品推荐

