Search code examples
pythontypeerrorgeneratorsnmppysnmp

pysnmp-lextudio using next() with the getCmd() generator leads to TypeError: 'tuple' object is not an iterator


I have removed pysnmp and installed pysnmp-lextudio in an attempt to bring my codebase up to python 3.12.2

Code that ran with previous pysnmp versions now returns the error: 'tuple' object is not an iterator

Offending code is next() of last line:

from pysnmp.hlapi import *
g = getCmd(SnmpEngine(),
    CommunityData('community', mpModel=1),
    UdpTransportTarget((ipAddress, port)),
    ContextData(),
    ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)))
        
errorIndication, errorStatus, errorIndex, varBinds = next(g)

Any insight is welcome, device behaving via snmp walk.


Solution

  • Because whereas the library pynsmp seems to return a generator from the getCmd function (see documentation, the pysnmp-lexstudio already performs the query.

    The example from pynsmp-lextudio site:

    >>> from pysnmp.hlapi import *
    >>> g = getCmd(SnmpEngine(),
    ...            CommunityData('public'),
    ...            UdpTransportTarget(('demo.pysnmp.com', 161)),
    ...            ContextData(),
    ...            ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)))
    >>> g
    (None, 0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.pysnmp.com 4.1.3_U1 1 sun4m'))])
    

    And from the pysnmp documentation:

    >>> from pysnmp.hlapi import *
    >>> g = getCmd(SnmpEngine(),
    ...            CommunityData('public'),
    ...            UdpTransportTarget(('demo.snmplabs.com', 161)),
    ...            ContextData(),
    ...            ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)))
    >>> next(g)
    (None, 0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m'))])
    

    Why this has changed, I don't know, but notice the missing next() on the first example.

    In fact, if you do just this:

    >>> print(getCmd(SnmpEngine(),
    ... CommunityData('community', mpModel=1),
    ... UdpTransportTarget((ipAddress, port)),
    ... ContextData(),
    ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0))))
    (RequestTimedOut('No SNMP response received before timeout'), 0, 0, [])
    

    You notice that the command is immediately called without next.

    So tl;dr: in your old version, g is a generator, in the new one it's a response.