-1

The code below is used as part of a SimpleXMLRPCServer to receive commands from a Java client I've written. The Java client will just call this execute function and pass in a function name from the CameraAssembler class.

from nsCamera.CameraAssembler import CameraAssembler
class MyFunctions:
    ca = None
    def initialize(self):
        # Create Camera object
        self.ca = CameraAssembler(commname=COMM, boardname=BOARD, sensorname=SENSOR, verbose=True)
        return True
    def execute(self, code):
        func = getattr(self.ca,code)
        output = func()
        return output

myfuncs = MyFunctions()
myfuncs.initialize()
output = myfuncs.execute('arm()')
print(output)

Output:

Traceback (most recent call last):
  File "pyTestServer.py", line 31, in <module>
    output = myfuncs.execute("arm()")
  File "pyTestServer.py", line 21, in execute
    func = getattr(MyFunctions.ca,code)
AttributeError: CameraAssembler instance has no attribute 'arm()'
TravisChambers
  • 526
  • 4
  • 12

1 Answers1

3

Your parentheses are in the wrong place. The attribute is not called arm(), it's called arm; you need to call the result of getting that attribute.

output = myfuncs.execute('arm')()

(Note, this code isn't particularly idiomatic. In particular, I can't see why you're setting ca as a class attribute, rather than an instance one. Also, initialisation usually goes in an __init__ method, which is called automatically on instantiation.)

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • 1
    `execute()` calls the function itself with `output = func()`. Unless `func()` returns another function, I don't think you should be calling the result of `execute()`. – Barmar May 19 '17 at 17:40
  • I can do it as an instance attribute instead, new to python, so I tried both to see if I had errors there instead. I'll edit the post – TravisChambers May 19 '17 at 17:42
  • @Barmar is right -- if i just call output = myfuncs.execute('arm') I'm good. – TravisChambers May 19 '17 at 17:43
  • as a follow up -- what if CameraAssembler had a method that required parameters? i.e. - `setPot(self, potname, value=1.0)` – TravisChambers May 19 '17 at 17:46
  • I recognize I should also use the `__init__` method, but in the future I'll pass in my own `BOARD` and `SENSOR` from the Java client, so I'll add those as parameters to the `initialize` method. With the built in `__init__` method, I can't pass these parameters from my Java client, right? – TravisChambers May 19 '17 at 17:51
  • Yes of course you can, you pass them as arguments to the instantiation call. – Daniel Roseman May 19 '17 at 17:58