tags:

views:

99

answers:

1

The snippet below is generating "weird" output:

for s in servers:
    vo = ss.getServerVO(s)
    values = []
    for f in voFields:
        attribValue = getattr(vo, f)
        values.append(attribValue)
    customValues = ss.getCustomFields(s)
    for f in customFields:
        values.append(customValues[f])
    # Convert all values to string before writing
    values = map(str, values)
    csvFile.writerow( values )

For some - not all - items in the customFields dictionary, I get the following output:

<bound method ServerVO.getCreatedDate of <pytwist.com.opsware.server.ServerVO instance at 0x3da8680>>

What do I need to do to get the bound method to execute / put its results into my values dictionary?

(Specific context is in writing a PyTwist script against the HP Server Automation API)

+1  A: 

You could try calling the bound method if it is one:

for f, v in customFields.iteritems():
  try:
    v = v()
  except TypeError:
    pass
  values.append(v)

The problem, of course, is with the design choice (by HP or whoever) to mix "accessors" with other kinds of values -- accessors are not a good Pythonic choice and should be replaced with properties (where this "call" gets automated for you where needed). This suggestion is about a possible way to work around that bad design choice.

Just trying to call, and checking for the TypeError that can result if the value is not callable (or not callable without arguments) is better than using callable or checking for a __call__ special method, because those checks would never tell you if "calling without argument" is OK. So, as usual in Python, "it's better to ask forgiveness by permission": try the operation, catch possible errors ("ask forgiveness") -- rather than try to check if the operation is permissible before attempting it ("ask permission").

Alex Martelli
This is quite elegant. Is using `if callable` ever a better option?
voyager
the API is actually in Java - it's just that the preferred access to the API is via the Python wrappers :)
warren
@voyager, can't think of any case -- `callable` can't tell you if "calling **without arguments**" is OK (and if arguments are needed, I can't think of any sensible way to guess how many, or which values, to pass as arguments).
Alex Martelli
@warren, thanks for clarifying this -- then it's the Python wrappers that have a questionable design (in Jython, accessors like `getFoo` are intrisically transformed into properties like `.foo` -- readonly if there's no `setFoo` to go with it, R/W if there is -- and that's a better way to translate idiomatic Java into idiomatic Python).
Alex Martelli
this seems to have helped *some* - but not all - of the `<bound method..` returns. My guess is that some of those are function pointers (or similar), and would require further recursing to parse-out. Thanks for the push in a direction.
warren