0

So, I am building a set of simple services, and I am tired of having to manually instantiate and hardcode a lot of things that I know Python can do dynamically. Specifically what I am trying to do is set up a simple service manager so that I can control power on/off/reset. Now, I already know how to get Python to do that actual function, but I want to abstract things out, so at a high level, the dev or user could do something like:

Service.power.reboot

I basically want to have a main class (Service) that can take as arguments a specific service and an action (power and reboot, respectively). This will have a network service, a storage service, etc. What I have done so far is the following:


class Service:

    def __init__(self, service, action):
        self.service = service
        self.action = action

    def start(self):  # action to be performed
        pass

    def stop(self):
        pass

    def restart(self):
        pass

    def enable(self):
        pass

    def disable(self):
        pass

    def status(self):
        pass

a pseudo code version of what I would like it to do which I think would be better and split up the code more:


Class Service:

    def __init__(self, service, action):
        self.service = service
        self.action = action

    def parse_request(self):
        # figure out what the user wants to do to what, return the class and method
        return serviceClass, serviceAction

    def do_what_the_user_wants(self):
        # call the class, run the method
        return class.method


class PowerService:

    def __init__(self, action):
        self.action = action

    def _parse_and_run_user_action_request:
        # voodoo here to iterate over the available methods for self and run
        return result

    def run(self):
       # run some power-related thing
       return result

    def stop(self):
        # stop some power-related thing
        return result

    etc...

In this case, the user is like Service('power', 'reboot') or more ideally, Service.power.reboot(), the service module takes in the arguments (or anything after the Service.), figures out which actual service to call and the method to run, and etc etc.

The service named Power is a class that inherits from this one, but I am wondering if I should do something during init to parse the arguments given, decide what it's going to do, and then dynamically call the class and perform the action given, without having to actually type out the classes individually. I am thinking like this would be better (no code, just showing the flow of what I mean):

user wants power to reboot -> Service class gets command use the power class and it's method reboot -> service class takes the two arguments, class the class and runs the method dynamically -> power class runs reboot method, returns status -> service class returns result to user

The main part that is confusing me is simply this: How do I make an impl/ API/factory or whatever to take a bunch of complex modules and use an API (of sorts) to take in strings or even dotted notation as arguments, so that the "API" class or impl or whatever will know what to do with them?

I just haven't found anything that really explains it properly. I know python can dynamically call functions, methods, classes and their associated attrs, props, etc. I just cannot find a concrete way or at least a design pattern that is making sense.

Sorry for the long-winded post.

ChristianYami
  • 586
  • 1
  • 9
  • 17
  • You can often pass an instance and the string name of a method into a class and the class does a lookup using getattr. – quamrana Apr 07 '20 at 20:46
  • Ok. Do you think you can show me an example or perhaps clarify how it works? I have read a few articles and tutorials and it's just not clicking. – RoninDusette Apr 07 '20 at 23:08
  • Here are examples of calling [functions](https://stackoverflow.com/questions/3061/calling-a-function-of-a-module-by-using-its-name-a-string) by their string name and calling [methods](https://stackoverflow.com/questions/18374447/how-to-call-method-by-string) by their string name. – quamrana Apr 08 '20 at 07:43

1 Answers1

0

There is another option which is to pass the method of an instance into a service class:

class Service:

    def __init__(self, action):
        self.action = action

    def doAction(self):  # action to be performed
        self.action()

class PowerService:

    def reboot(self):
        # Do some booty things

power = PowerService()

rebooter = Service(power.reboot)

rebooter.doAction()  # calls power.reboot()
quamrana
  • 37,849
  • 12
  • 53
  • 71