1

In the python module pysnmp there is a function named cmdGen.nextCmd with the following definition

nextCmd(authData,
        transportTarget,
        *varNames, # <------- point of interest
        lookupNames=False,
        lookupValues=False,
        lexicographicMode=False,
        ignoreNonIncreasingOid=False,
        maxRows=0)

I can call this function this way:

errorIndication, errorStatus, errorIndex, varBindTable = cmdGen.nextCmd(
  cmdgen.CommunityData('public'),
  cmdgen.UdpTransportTarget(('192.168.0.1', 161)),
  '1.3.6.1.4.1.14988.1.1.1.2.1.3', # strength
  '1.3.6.1.4.1.14988.1.1.1.2.1.4', # tx-bytes
  '1.3.6.1.4.1.14988.1.1.1.2.1.5', # rx-bytes
  lookupValues=False
)

apparently the oid's (strength, tx-bytes, rx-bytes) are passed to the nextCmd function via the *varNames parameter.

I'm trying to archive something along these lines:

oids = (                           # dynamically generated
  '1.3.6.1.4.1.14988.1.1.1.2.1.3', # strength
  '1.3.6.1.4.1.14988.1.1.1.2.1.4', # tx-bytes
  '1.3.6.1.4.1.14988.1.1.1.2.1.5'  # rx-bytes
)

errorIndication, errorStatus, errorIndex, varBindTable = cmdGen.nextCmd(
  cmdgen.CommunityData('public'),
  cmdgen.UdpTransportTarget(('192.168.0.1', 161)),
  oids, # these are the oid's
  lookupValues=False
)

but it does yield a

AttributeError: 'tuple' object has no attribute 'split'

How can bundle the oid's into a variable and pass them to the nextCmd? I'm extracting the oid's from a dict, so I don't want to hard-code them.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Daniel F
  • 13,684
  • 11
  • 87
  • 116

2 Answers2

3

You need to use the *args syntax in the call here:

errorIndication, errorStatus, errorIndex, varBindTable = cmdGen.nextCmd(
  cmdgen.CommunityData('public'),
  cmdgen.UdpTransportTarget(('192.168.0.1', 161)),
  *oids,
  lookupValues=False
)

This passes in each value in oids as a separate argument.

Note that this is a different but deliberately similar concept to using *args in a function signature. In a call, it expands the positional arguments, in a function signature the same syntax captures extra positional arguments.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Thanks, that worked. Does this *args have a special name? In https://docs.python.org/2/tutorial/controlflow.html#unpacking-argument-lists I see that this might be referred to as "packed arguments", is that the "slang"? – Daniel F Mar 04 '15 at 13:17
  • @DanielF: there isn't really any, no. The canonical question on the syntax is [What does \*\* (double star) and \* (star) do for Python parameters?](http://stackoverflow.com/q/36901) and the [reference documentation for calls](http://stackoverflow.com/questions/36901/what-does-double-star-and-star-do-for-python-parameters) or [for function definitions](https://docs.python.org/2/reference/compound_stmts.html#function-definitions) offer no better options. – Martijn Pieters Mar 04 '15 at 13:19
  • The official tutorial calls them [`arbitrary arguments lists`](https://docs.python.org/dev/tutorial/controlflow.html#arbitrary-argument-lists) – d6bels Mar 04 '15 at 13:21
  • @d6bels: that's the function definition side. It also uses the term *variadic arguments*. On the *calling side* it calls this [*unpacking argument lists*](https://docs.python.org/dev/tutorial/controlflow.html#unpacking-argument-lists). – Martijn Pieters Mar 04 '15 at 13:21
  • Ok, so I see that these are referred to as "excess positional parameters", which implies that they go before kwargs. Ahh.. Oh.. ok. Anyway, good to know that I can also "inject" some extras via *oids. – Daniel F Mar 04 '15 at 13:25
1

This is like an argument list so you just need to put a * in front of oids to get it working.

This will unpack the tuple just as if you had given each oid as a plain argument.

Your code :

errorIndication, errorStatus, errorIndex, varBindTable = cmdGen.nextCmd(
  cmdgen.CommunityData('public'),
  cmdgen.UdpTransportTarget(('192.168.0.1', 161)),
  *oids, # these are the oid's
  lookupValues=False
)
d6bels
  • 1,432
  • 2
  • 18
  • 30