开发者

Python use a virtual class to apply a generic "pipe" pattern

I am trying to find out if it would be possible to take the fol开发者_如何学Pythonlowing code, and use the magic of python to simplify code.

Right now I have a command interface that sits on top of a bunch of python sub processes. When I need to communicate with the sub process's I pipe commands to them. Basically it comes down to a string command, and a dictionary of arguments.

Here is the pattern that gets repeated (I showed 1 for simplicitys sake but in reality this is repeated 7 times for different processes)

Create the processes:

class MasterProcess(object):
 def __init__(self):
  self.stop = multiprocessing.Event()

  (self.event_generator_remote, self.event_generator_in)
       =     multiprocessing.Pipe(duplex=True)
  self.event_generator= Process(target=self.create_event_generator, 
                            kwargs={'in':   self.event_generator_remote} 
                    )
  self.event_generator.start()

 def create_event_generator(self, **kwargs):
      eg= EventGenerator()
      in_pipe = kwargs['in']

      while(not self.stop.is_set()):
            self.stop.wait(1)
            if(in_pipe.poll()):
               msg = in_pipe.recv()
               cmd = msg[0]
               args = msg[1]
               if cmd =='create_something':
                   in_pipe.send(eg.create(args))
               else:
                   raise NotImplementedException(cmd)

And then on the command interface is just pumping commands to the process:

 mp.MasterProcess()
 pipe =  mp.event_generator_remote

 >>cmd:  create_something args

 #i process the above and then do something like the below 

 cmd = "create_something"
 args = {
      #bah
 }
 pipe.send([command, args])

 attempt = 0
 while(not pipe.poll()):
    time.sleep(1)
    attempt +=1
    if attempt > 20:
        return None
     return pipe.recv()

What I want to move to is more of a remote facade type deal where the client just calls a method like it would normally, and I translate that call to the above.

For example the new command would look like:

mp.MasterProcess()
mp_proxy = MasterProcessProxy(mp.event_generator_remote)
mp_proxy.create_something(args)

So my virtual class would be MasterProcessProxy, there are really no methods behind the scenes somehow take the method name, and provided args and pipe them to the process?

Does that make sense? Would it be possible to do the same on the other side? Just assume whatever comes down the pipe will be in the form cmd , args where cmd is a local method? and just do a self.() ?

As I am typing this up I understand it is probably confusing, so please let me know what needs clarification.

Thanks.


You can use __getattr__ to create proxy methods for your stub class:

class MasterProcessProxy(object):

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

    # This is called when an attribute is requested on the object.
    def __getattr__(self, name):
        # Create a dynamic function that sends a command through the pipe
        # Keyword arguments are sent as command arguments.
        def proxy(**kwargs):
            self.pipe.send([name, kwargs])
        return proxy

Now you can use it as you wanted:

mp.MasterProcess()
mp_proxy = MasterProcessProxy(mp.event_generator_remote)
mp_proxy.create_something(spam="eggs", bacon="baked beans")
# Will call pipe.send(["create_something", {"spam":"eggs", "bacon":"baked beans"}])


You might want to check out the twisted framework. This won't beat figuring out how to do it yourself, but will make writing this style of application a lot easier.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜