Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to archive real time communication between Python and JS ? #3533

Open
nukadelic opened this issue Apr 15, 2018 · 1 comment
Open

How to archive real time communication between Python and JS ? #3533

nukadelic opened this issue Apr 15, 2018 · 1 comment

Comments

@nukadelic
Copy link

nukadelic commented Apr 15, 2018

My goal is to run JS canvas-game within a notebook and get continues data stream between itself and Python. First i have tried to execute notebook kernel from JS, 60 times per second, with an animation frame request hook. But then it hit me, this process is working on a single kernel. Here is my initial attempt:

%%javascript
window.onEnterFrame = e => IPython.notebook.kernel.execute(
`sharedVariable = "${ window.getGameVar() }"  `
);

So that resulted in non changing sharedVariable value during the cell execution

import time
result_1 = sharedVariable
time.sleep( 1 )
result_2 = sharedVariable
print( result_1 == result_2 ) # output is always True

After which i have decided to try and use the COMM, so I made a simple one that will replay with a string value after 500ms of delay.

%%javascript
Jupyter.notebook.kernel.comm_manager.register_target('my_comm_id', (comm, msg)=> {
    comm.on_msg(_=> { // on msg received 
        setTimeout( _=> { // wait 500ms
            comm.send(  window.getGameVar()  ); // output data
        }, 500 );
    });
});

And a matching Python COMM:

my_comm = Comm( target_name='my_comm_id' )
@my_comm.on_msg
def _recv(msg):
    global sharedVariable
    sharedVariable = msg['content']['data']

But that didn't help either, as apparently the messaged were getting received only after the cell had completed it's execution

my_comm.send( "" )
time.sleep( 1 )
result_1 = sharedVariable
my_comm.send( "" )
time.sleep( 1 )
result_2 = sharedVariable
print( result_1 == result_2 ) # output is always True

Also i have tried creating a separate async function

import asyncio

async def getData2(future):
    global my_comm, sharedVariable
    my_comm.send( "" )
    await asyncio.sleep(1)
    future.set_result( sharedVariable )

def getData():
    asyncio.set_event_loop(asyncio.new_event_loop()) # set new global event loop
    loop = asyncio.get_event_loop()
    future = asyncio.Future()
    asyncio.ensure_future( getData2(future) )
    loop.run_until_complete(future)
    result = future.result()
    loop.close()
    return result

But the problem didn't go away

result_1 = getData()
result_2 = getData()
print( result_1 == result_2 ) # output is always True

I had a brief overview of ipywidgets and was able to get one way communication to work like so:

from ipywidgets import FloatSlider
from IPython.display import display
slider = FloatSlider()
display(slider)
for i in range( 11 ):
    slider.value = i * 10    
    time.sleep( 1 )

But the widgets won't work if you change the slider by dragging it

for i in range( 10 ):
    print( slider.value )  # Will always output slider initial value
    time.sleep( 1 ) 
@kkyon
Copy link

kkyon commented Sep 15, 2018

You need to find some widgets has internal envent loop . Then be able to be added callback function to update/refresh data. Aboves you tried seem do "push" data work . It only can work when buld yourself widgets.

see below some widgets.
bokeh
and
https://ipywidgets.readthedocs.io/en/stable/examples/Widget%20Asynchronous.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants