-2

I am trying to develop remote procedure call framework in python and I have a problem with exec() function. Simplified scenario:

class Example:
  def __init__():
    pass

  def add(self, string):
    return anothermodule.func(self,string)


class Framework:

  def function_call():
     exec("a = exampleObject.add(string)")

It seems impossible to call a function with exec() which has another function inside of it. I have tried but I always get "wrong number of parameters". In debugging mode I don't even get transfered to the "add" function in order to see what's happening.

This however, works normally.

class Example:
  def __init__():
    pass

  def add(self, x):
    return x + 3

class Framework:

  def function_call():
     exec("a = exampleObject.add(8)")


def main():
  framework = Framework()
  framework.function_call()

exampleObject is created dynamically in another class based on parameter provided in another method. It's just the instance of the Example class. This is only simplified version of what I am trying to achieve. It does not represent my exact code. What I am trying to say is, that my exec() only works on simple operation and is somehow not able to call another method inside the original one.

EDIT

class Calculator():
    def add(self,a,b):
        return a + b

    def testFunction(self,a,b):
        return self.add(self,a,b)


def main():
    # Create new client object, specifying redis server and channel
    remote_calculator = rpcpyredis.Proxy("localhost", "Calculator", port=6379)

    # Calling any method with client object
    result = remote_calculator.testFunction(3,4)


 if __name__== '__main__':
    main()


class Server:
    def execute_code(self, calling_function, class_type):
        object = class_type()
        final_function_call = 'self.result = object.' + calling_function
        exec(final_function_call)
        return self.result

  def make_function(self, request):
      args = request["params"]
      arguments = ",".join((str(i) for i in args))
      method_name = (request["function"])
      return '%s(%s)' % (method_name, arguments)

      def start():
          class_type = registry.lookup(object_to_lookup_for)
          calling_function = self.make_function(extracted_request)
          rpc_response = self.execute_code(calling_function, class_type)
Nikolas Stevenson-Molnar
  • 4,235
  • 1
  • 22
  • 31
Pegasus Thorn
  • 159
  • 1
  • 2
  • 12
  • 2
    Please show in your code example where `exampleObject` is created. – Nikolas Stevenson-Molnar Feb 14 '19 at 22:35
  • 1
    Your `__init__` method is missing parens: `def __init__():` – Nikolas Stevenson-Molnar Feb 14 '19 at 22:39
  • When posting simplified code, you have to post something that *runs* and *demonstrates the error* when run. It's fine if you take out all the remote procedure call stuff, as long as you leave in what's necessary to reproduce the error. We can't debug this. – user2357112 Feb 14 '19 at 22:46
  • It's possible that the `final_function_call` is not being constructed the way you expect. For example, is `calling_function` perhaps just the function _name_, without arguments? Have you tried printing `final_function_call` to make sure it's what you expect? – Nikolas Stevenson-Molnar Feb 14 '19 at 23:31
  • Yes, actually I debugged it and it looks correct. I thought maybe it can not be done in general, maybe is something wrong within this "nested" call. Could not find anything on the internet. – Pegasus Thorn Feb 14 '19 at 23:41

1 Answers1

1

From your example, I don't think the problem is with your call to exec() at all. Rather, it's in the testFunction method:

def testFunction(self,a,b):
    return self.add(self,a,b)

Note that you are providing self in your call to self.add(self, a, b). self is always included implicitly in method calls, so that line is essentially calling self.add(self, self, a, b), which does, indeed have the wrong number of arguments.

That should fix your error. But aside from all that, you should never use exec().

Nikolas Stevenson-Molnar
  • 4,235
  • 1
  • 22
  • 31