dbousque / lymp

Use Python functions and objects from OCaml
MIT License
72 stars 1 forks source link

parallel interactive session #6

Open nilsbecker opened 7 years ago

nilsbecker commented 7 years ago

is it possible to either attach lymp to a running ipython process or to spawn an ipython process from lymp such that i can interact with it in another shell?

nilsbecker commented 7 years ago

i tried the following: start an ipython kernel with jupyter console then from within lymp, try to initialize with "ipython console --existing /Users/nbecker/Library/Jupyter/runtime/kernel-61547.json" which is what one would do from a shell. however, this did not work as expected

dbousque commented 7 years ago

I there, I will look into it, it would be great to be able to interact with ipython, thanks for suggesting. I will let you know how it goes.

LucasMembrane commented 6 years ago

Could one get the parallel processes by changing the python 'return' statements to 'yield' statements?

dbousque commented 6 years ago

Hi @LucasMembrane. You could write a small wrapper around it I guess, do you have a specific use case in mind ?

LucasMembrane commented 6 years ago

I've just first looked at this, and it appears that lymp facilitates calling python from ocaml much easier than any way of calling ocaml from python, which is what I have thought would be a good way to go for GUI apps, web apps, etc, with the UI in python and the hard-core algorithms in OCaml. It is possible to invert control through an A calls B type interface so that B is actually in control, where each call from A asks for the next command from B. Having python yield a series of commands (perhaps from within a loop) might make that even a little more attractive.

dbousque commented 6 years ago

There would be ugly ways to do it using lymp, but I don't think this package would be appropriate for what you have in mind I'm afraid. One ugly way I can think of : you could launch a Python process from OCaml (Lymp.init), and call some Python function that would start your application in a separate thread, doing your actual business. Then OCaml would ask Python for some work to do, and the Python process would only return when there is something to do. It might look something like (kind of pseudocode) :

open Lymp

let ml_sum = (+)

let () =
  let interpreter = "python3"
  let py = init ~exec:interpreter "."
  let py_to_ml = get_module py "py_to_ml"
  call py_to_ml "init" [] ;
  while true do
    let instruction = get_list py_to_ml "what_to_do" [] in
    let instruction_name = List.nth instruction 0 in
    match instruction_name with
    | Pystr "ml_sum" -> (
      let arg1 = match (List.nth instruction 1) with | Pyint i -> i | _ -> 0
      let arg2 = match (List.nth instruction 2) with | Pyint i -> i | _ -> 0
      call py_to_ml "here_is_the_result" [Pyint (ml_sum arg1 arg2)]
    )
  done

py_to_ml.py

ml_mutex = None
to_send_to_ml = None
res_from_ml = None

def init():
  # launch application in separate thread
  # lock ml_mutex
  return

def what_to_do():
  # wait for mutex to be unlocked and take the lock
  return to_send_to_ml

def here_is_the_result(*res)
  res_from_ml = res
  # unlock ml_mutex
  return

def call_ml_function(function_name, args)
  to_send_to_ml = [function_name] + args
  # unlock ml_mutex
  # wait for mutex to be unlocked and take the lock
  return res_from_ml

There you go, you can now call call_ml_function like so from your Python application : call_ml_function("ml_sum", [20, 22]), and receive [42] back :) I would advice against doing something like that in a production environment though.