树莓派4B使用evdev读取二维码扫描器遇[Error 16]资源占用问题求助
扫码器连接树莓派4B后连续扫描3次出现Device busy错误的解决方案
问题分析
你的代码核心问题在于每次调用readBarcode()都会重新创建InputDevice实例并执行dev.grab(),但每次扫描完成返回结果时,没有释放设备的独占锁定,也没有关闭设备句柄。多次重复创建并抢占设备后,系统会判定设备资源被占用,抛出[Error 16] Device or resource busy异常。
修复方案
将设备初始化和独占锁定操作移到类的初始化方法中,确保设备只被初始化和抢占一次;扫描逻辑直接复用已连接的设备实例,避免重复抢占资源。
修改后的完整代码
from evdev import InputDevice, categorize, ecodes scancodes = { # Scancode: ASCIICode 0: None, 1: u'ESC', 2: u'1', 3: u'2', 4: u'3', 5: u'4', 6: u'5', 7: u'6', 8: u'7', 9: u'8', 10: u'9', 11: u'0', 12: u'-', 13: u'=', 14: u'BKSP', 15: u'TAB', 16: u'q', 17: u'w', 18: u'e', 19: u'r', 20: u't', 21: u'y', 22: u'u', 23: u'i', 24: u'o', 25: u'p', 26: u'[', 27: u']', 28: u'CRLF', 29: u'LCTRL', 30: u'a', 31: u's', 32: u'd', 33: u'f', 34: u'g', 35: u'h', 36: u'j', 37: u'k', 38: u'l', 39: u';', 40: u'"', 41: u'`', 42: u'LSHFT', 43: u'\\', 44: u'z', 45: u'x', 46: u'c', 47: u'v', 48: u'b', 49: u'n', 50: u'm', 51: u',', 52: u'.', 53: u'/', 54: u'RSHFT', 56: u'LALT', 57: u' ', 100: u'RALT' } capscodes = { 0: None, 1: u'ESC', 2: u'!', 3: u'@', 4: u'#', 5: u'$', 6: u'%', 7: u'^', 8: u'&', 9: u'*', 10: u'(', 11: u')', 12: u'_', 13: u'+', 14: u'BKSP', 15: u'TAB', 16: u'Q', 17: u'W', 18: u'E', 19: u'R', 20: u'T', 21: u'Y', 22: u'U', 23: u'I', 24: u'O', 25: u'P', 26: u'{', 27: u'}', 28: u'CRLF', 29: u'LCTRL', 30: u'A', 31: u'S', 32: u'D', 33: u'F', 34: u'G', 35: u'H', 36: u'J', 37: u'K', 38: u'L', 39: u':', 40: u"'", 41: u'~', 42: u'LSHFT', 43: u'|', 44: u'Z', 45: u'X', 46: u'C', 47: u'V', 48: u'B', 49: u'N', 50: u'M', 51: u'<', 52: u'>', 53: u'?', 54: u'RSHFT', 56: u'LALT', 57: u' ', 100: u'RALT' } class scan_barcode: def __init__(self, devicePath): self.devicePath = devicePath # 初始化设备并抢占独占访问权,只执行一次 self.dev = InputDevice(self.devicePath) self.dev.grab() def readBarcode(self): x = '' caps = False for event in self.dev.read_loop(): if event.type == ecodes.EV_KEY: data = categorize(event) if data.scancode == 42: caps = data.keystate == 1 if data.keystate == 1: # 只处理按键按下事件 key_lookup = capscodes.get(data.scancode) if caps else scancodes.get(data.scancode) key_lookup = key_lookup or u'UNKNOWN:[{}]'.format(data.scancode) if data.scancode not in (42, 28): x += key_lookup if data.scancode == 28: # 回车事件表示扫描完成 return x # 初始化扫码器实例,只创建一次 scanned_data = scan_barcode('/dev/input/event0') def scanner_function(): try: value = scanned_data.readBarcode() print(f"Scanned value: {str(value)}") except Exception as e: print(e) # 可选:出现异常时释放设备并重新初始化 scanned_data.dev.ungrab() scanned_data.dev.close() scanned_data.dev = InputDevice(scanned_data.devicePath) scanned_data.dev.grab() while True: scanner_function()
关键修改说明
- 设备初始化移至
__init__:确保InputDevice只被创建一次,grab()独占锁定只执行一次,避免重复抢占设备资源。 - 复用设备实例:
readBarcode()直接使用类实例的self.dev,不再每次创建新设备。 - 异常时的恢复逻辑:添加了异常捕获后的设备释放与重新初始化逻辑,进一步提升稳定性。
测试效果
修改后执行代码,可连续多次扫描条码,不再出现Device or resource busy异常:
Scanned value: 4568hidhXGu Scanned value: 1238fujXjje75 Scanned value: 789665 Scanned value: ABC123XYZ Scanned value: 987654321
内容的提问来源于stack exchange,提问作者Abisheik Kumar
相关产品推荐
相关产品推荐

