So in an IPython Jupyter notebook one can add JavaScript functions via the %% javascript magic cell syntax or via the Python kernel with IPython.display.HTML and one can alter Python variables in JS with IPython.notebook.kernel.execute.
However, the kernel call is done when the kernel is idle.
cell 1, magic cell JS to add the function.
%%javascript
window.act = () => IPython.notebook.kernel.execute('flag = False');
cell 2, python kernel
from IPython.display import display, HTML
flag = True
display(HTML('''<p id="newDOMElement">New DOM element added </div>
<script type="text/Javascript">
act();
$('#newDOMElement').append('<b>and changed</b>.');
</script>'''))
import time
time.sleep(2) #wait in case it's a JS async issue.
print('JS did not change Py variable.' if flag else 'JS successfully changed Py variable.')
>> New DOM element added and changed.
>> JS did not change Py variable.
The result shows the JS is working and changing the #newDOMElement element. But the kernel did not change as it waited.
In fact, once the cell was done with the kernel, the variable changed. As show with this.
print('JS did not change Py variable.' if flag else 'JS successfully changed Py variable.')
>> JS successfully changed Py variable.
This experiment means that one cannot wrap the JS function in a Python method that changes data continually at runtime. Is there a way around this?
Code sent to the kernel is executed one snippet at a time. Although you're calling sleep, the cell is still executing. So the snippet sent by JS won't be executed until after the cell is done, as you've observed.
If you want to do something asynchronously, you could send a custom message through the Jupyter protocol from the browser to the kernel, and install a custom message handler in the Python kernel to process it. Some attempts in that direction are linked in the "Previous work" section of IPEP-8:
https://github.com/ipython/ipython/wiki/IPEP-8:-Custom-messages-and-message-handlers#previous-work
来源:https://stackoverflow.com/questions/56671009/workaround-for-wrapping-a-js-function-in-python-in-jupyter-notebook