views:

565

answers:

2

I would like to create a shell which will control a separate process that I created with the multiprocessing module. Possible? How?

EDIT:

I have already achieved a way to send commands to the secondary process: I created a code.InteractiveConsole in that process, and attached it to an input queue and an output queue, so I can command the console from my main process. But I want it in a shell, probably a wx.py.shell.Shell, so a user of the program could use it.

A: 

You can create a Queue which you pass to the separate process. From the Python Docs:

from multiprocessing import Process, Queue

def f(q):
    q.put([42, None, 'hello'])

if __name__ == '__main__':
    q = Queue()
    p = Process(target=f, args=(q,))
    p.start()
    print q.get()    # prints "[42, None, 'hello']"
    p.join()

EXAMPLE: In the wx.py.shell.Shell Docs the constructur parameters are given as

__init__(self, parent, id, pos, size, style, introText, locals, 
         InterpClass, startupScript, execStartupScript, *args, **kwds)

I have not tried it, but locals might be a dictionary of local variables, which you can pass to the shell. So, I would try the following:

def f(cmd_queue):
    shell = wx.py.shell.Shell(parent, id, pos, size, style, introText, locals(),
                              ...)

q = Queue()
p = Process(target=f, args=(q,))
p.start()

Inside the shell, you should then be able to put your commands into cmd_queue which have then to be read in the parent process to be executed.

wr
Please be more specific about how this lets me create a shell that controls my secondary Process.
cool-RR
In your example, the secondary process is creating the Shell, a wx object. Do you think it is possible to create a wx object from the secondary process, even though the main process creates the wx.App and all the other wx objects?
cool-RR
+1  A: 
  1. First create the shell
  2. Decouple the shell from your app by making its locals empty
  3. Create your code string
  4. Compile the code string and get a code object
  5. Execute the code object in the shell
    from wx.py.shell import Shell

    frm = wx.Frame(None)
    sh = Shell(frm)
    frm.Show()    
    sh.interp.locals = {}
    codeStr = """
    from multiprocessing import Process, Queue

    def f(q):
        q.put([42, None, 'hello'])

    q = Queue()   
    p = Process(target=f, args=(q,))
    p.start()
    print q.get()    # prints "[42, None, 'hello']"
    p.join()
    """

    code = compile(codeStr, '', 'exec')
    sh.interp.runcode(code)

Note: The codeStr I stole from the first poster may not work here due to some pickling issues. But the point is you can execute your own codeStr remotely in a shell.

I don't understand. What I want is a shell where the user can type in Python commands, and they get sent to the secondary process. Is this what I'm getting here? Because I don't understand that codeStr thing.
cool-RR
codeStr was an example to show how to create a code object and execute it remotely in the shell.If all you need is executing the commands from the shell in another process then you need to create a custom interpreter class inheriting from the Interpreter class (located in interpreter.py in the py package).In your custom interpreter overwrite the runsource method so that it uses the "source" argument to create a code object and then executes this code object in a separate process. Now you have a customized interpreter class. sh = Shell(frm, InterpClass=yourInterpreter)This should do it.
I'm still confused. I went over interpreter.py and code.py. Are you sure I only have to overwrite `runsource`? What about `runcode`?
cool-RR