我需要编写简单的simple,其中一部分工作是通过asyncio.subprocess模块调用一些外部脚本。现在,我正在试验pysnmp,但是按照示例中稍作修改的代码不起作用:
import asyncio
from pysnmp.entity import engine, config
from pysnmp.entity.rfc3413 import cmdrsp, context
from pysnmp.carrier.asyncio.dgram import udp
from pysnmp.smi import instrum
from pysnmp.proto.api import v2c
snmpEngine = engine.SnmpEngine()
config.addTransport(
snmpEngine,
udp.domainName,
udp.UdpTransport().openServerMode(('0.0.0.0', 161))
)
# config.addV1System(snmpEngine, 'my-area', 'public')
config.addV1System(snmpEngine, 'public', 'public', contextName='my-context')
config.addV1System(snmpEngine, 'private', 'private', contextName='my-context')
# Allow full MIB access for each user at VACM
config.addVacmUser(snmpEngine, 2, "public", 'noAuthNoPriv', (1, 3, 6, 1, 2, 1), (1, 3, 6, 1, 2, 1))
config.addVacmUser(snmpEngine, 2, "private", 'noAuthNoPriv', (1, 3, 6, 1, 2, 1), (1, 3, 6, 1, 2, 1))
# Create an SNMP context
snmpContext = context.SnmpContext(snmpEngine)
# Very basic Management Instrumentation Controller without
# any Managed Objects attached. It supports only GET's and
# always echos request var-binds in response.
class EchoMibInstrumController(instrum.AbstractMibInstrumController):
@asyncio.coroutine
def readVars(self, varBinds, acInfo=(None, None)):
yield from asyncio.sleep(1)
return [(ov[0], v2c.OctetString('You queried OID %s' % ov[0])) for ov in varBinds]
# Create a custom Management Instrumentation Controller and register at
# SNMP Context under ContextName 'my-context'
snmpContext.registerContextName(
v2c.OctetString('my-context'), # Context Name
EchoMibInstrumController() # Management Instrumentation
)
# Register GET&SET Applications at the SNMP engine for a custom SNMP context
cmdrsp.GetCommandResponder(snmpEngine, snmpContext)
cmdrsp.SetCommandResponder(snmpEngine, snmpContext)
loop = asyncio.get_event_loop()
loop.run_forever()当尝试使用以下命令进行查询时,snmpget -v 2c -c public 127.0.0.1 .1.3.6.1.2.1.1.1.0脚本将使用以下回溯失败。
Exception in callback AbstractTransportDispatcher._cbFun(<pysnmp.carri...x7f4c7540d518>, ('127.0.0.1', 44209), b'0)\x02\x01\...1\x00\x05\x00')
handle: <Handle AbstractTransportDispatcher._cbFun(<pysnmp.carri...x7f4c7540d518>, ('127.0.0.1', 44209), b'0)\x02\x01\...1\x00\x05\x00')>
Traceback (most recent call last):
File "/usr/lib/python3.4/asyncio/events.py", line 120, in _run
self._callback(*self._args)
File "/opt/profiset2/lib/python3.4/site-packages/pysnmp/carrier/base.py", line 70, in _cbFun
self, transportDomain, transportAddress, incomingMessage
File "/opt/profiset2/lib/python3.4/site-packages/pysnmp/entity/engine.py", line 154, in __receiveMessageCbFun
self, transportDomain, transportAddress, wholeMsg
File "/opt/profiset2/lib/python3.4/site-packages/pysnmp/proto/rfc3412.py", line 421, in receiveMessage
PDU, maxSizeResponseScopedPDU, stateReference)
File "/opt/profiset2/lib/python3.4/site-packages/pysnmp/entity/rfc3413/cmdrsp.py", line 140, in processPdu
(self.__verifyAccess, snmpEngine))
File "/opt/profiset2/lib/python3.4/site-packages/pysnmp/entity/rfc3413/cmdrsp.py", line 247, in handleMgmtOperation
mgmtFun(v2c.apiPDU.getVarBinds(PDU), (acFun, acCtx)))
File "/opt/profiset2/lib/python3.4/site-packages/pysnmp/entity/rfc3413/cmdrsp.py", line 46, in sendVarBinds
v2c.apiPDU.setVarBinds(PDU, varBinds)
File "/opt/profiset2/lib/python3.4/site-packages/pysnmp/proto/api/v1.py", line 135, in setVarBinds
varBindList.getComponentByPosition(idx), varBind
File "/opt/profiset2/lib/python3.4/site-packages/pysnmp/proto/api/v1.py", line 38, in setOIDVal
oid, val = oidVal[0], oidVal[1]
TypeError: 'Future' object does not support indexing也许我正在做一些愚蠢的事情,我承认我对SNMP不太了解,那么,请给我指明正确的方向。
发布于 2017-03-11 18:28:16
这是因为CommandResponder <-> MIB控制器交互是当前同步。换句话说,您不能使用yield from MIB控制器,您只能从它获得return。它不可能是coroutine。一旦删除了这两件事,您的代码可能会正常工作。
用一种mgmtFun (在我前面链接的代码中)可以返回Future的方式重构pysnmp代码是绝对可行的,Future一旦完成Future就会触发其余的代码(例如sendVarBinds)。这将使您的MIB控制器异步。
这就是你需要的吗?然后考虑一下PR或FR来对抗脓抽筋症。
https://stackoverflow.com/questions/42738005
复制相似问题