注册自定义OID处理器报错:MsgAndPduDispatcher无getNextReqMsgID属性
解决pysnmp中'MsgAndPduDispatcher'无'getNextReqMsgID'属性的错误
问题场景
尝试用pysnmp编写SNMP服务端,注册自定义OID响应GET请求时,触发错误:
AttributeError: 'MsgAndPduDispatcher' object has no attribute 'getNextReqMsgID'
错误出现在这行代码:
reqMsgID = snmpEngine.msgAndPduDsp.getNextReqMsgID()
问题原因
- 当前使用的pysnmp版本已移除
MsgAndPduDispatcher.getNextReqMsgID()方法,原有调用方式失效 - 直接操作
msgAndPduDsp注册OID的方式不符合pysnmp标准用法,正确做法是通过MIB仪器化(Instrumentation)实现自定义OID的响应逻辑
修正后的完整代码
from pysnmp.carrier.asyncio.dgram import udp from pysnmp.entity import engine, config from pysnmp.entity.rfc3413 import cmdresp from pysnmp.smi import builder, exval, rfc1902 from pysnmp.proto import rfc1902 # 创建SNMP引擎实例 snmpEngine = engine.SnmpEngine() # 加载自定义MIB(不需要可跳过此段) mibBuilder = snmpEngine.getMibBuilder() mibPath = mibBuilder.getMibSources() + (builder.DirMibSource('/home/pi/'),) mibBuilder.setMibSources(*mibPath) mibBuilder.loadModules('MY-MIB') # 自定义OID处理函数 def custom_oid_handler(snmp_engine, context_engine_id, context_name, var_binds, cb_ctx): results = [] for oid, val in var_binds: if oid == (1, 3, 6, 1, 4, 1, 123456, 1): # 返回自定义字符串值 results.append((oid, rfc1902.OctetString("Custom value for OID 1.3.6.1.4.1.123456.1"))) else: # 未知OID返回标准错误 results.append((oid, exval.noSuchObject)) cb_ctx['cbFun'](snmp_engine, context_engine_id, context_name, results, cb_ctx) # 绑定处理函数到MIB仪器控制器 mibInstrum = snmpEngine.msgAndPduDsp.mibInstrumController mibInstrum.registerReadVarsCallback(custom_oid_handler) # 创建UDP服务端传输 udpServerTransport = udp.UdpTransport().openServerMode(('0.0.0.0', 161)) # 配置SNMPv1社区字符串 community = config.CommunityData('public') config.addV1System(snmpEngine, 'my-area', community) # 配置VACM访问控制,允许读取1.3.6开头的OID树 config.addVacmUser(snmpEngine, 1, 'my-area', 'noAuthNoPriv', (1, 3, 6), (1, 3, 6)) # 启动SNMP命令响应器(处理GET/SET请求) cmdresp.CmdResponder(snmpEngine) snmpEngine.transportDispatcher.registerTransport(udpServerTransport) snmpEngine.transportDispatcher.jobStarted(1) print("SNMP server listening on port 161") # 启动事件循环维持服务运行 try: snmpEngine.transportDispatcher.runDispatcher() except Exception as e: snmpEngine.transportDispatcher.closeDispatcher() raise e
关键修正点
- 补全缺失的
engine、config、cmdresp核心模块导入 - 移除错误的
getNextReqMsgID调用和registerContextEngineId用法,改用registerReadVarsCallback注册自定义OID读取逻辑 - 替换
NotificationReceiver为CmdResponder:前者仅处理SNMP陷阱/通知,后者才是处理GET/SET请求的正确组件 - 完善事件循环逻辑,确保服务持续运行
内容的提问来源于stack exchange,提问作者otuga
相关产品推荐
相关产品推荐

