在 Jupyter 笔记本中用 python 包装 JS 函数的解决方法

Mat*_*rla 4 javascript python jupyter-notebook

因此,在 IPython Jupyter 笔记本中,您可以通过%% javascript魔术单元语法或通过 Python 内核添加 JavaScript 函数,IPython.display.HTML并且可以使用IPython.notebook.kernel.execute.

但是,内核调用是在内核空闲时完成的。

单元格1,魔术单元JS添加功能。

%%javascript
window.act = () => IPython.notebook.kernel.execute('flag = False');
Run Code Online (Sandbox Code Playgroud)

单元 2,python 内核

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.
Run Code Online (Sandbox Code Playgroud)

结果显示 JS 正在工作并正在更改#newDOMElement元素。但是内核在等待时并没有改变。事实上,一旦单元用内核完成,变量就会改变。正如这个所示。

print('JS did not change Py variable.' if flag else 'JS successfully changed Py variable.')
>> JS successfully changed Py variable.
Run Code Online (Sandbox Code Playgroud)

这个实验意味着不能将 JS 函数包装在一个在运行时不断改变数据的 Python 方法中。有没有解决的办法?

Rol*_*ber 5

发送到内核的代码一次执行一个片段。尽管您正在调用sleep,但该单元仍在执行。因此,正如您所观察到的,在单元格完成之前,JS 发送的代码段不会被执行。

如果要异步执行某些操作,可以通过 Jupyter 协议从浏览器向内核发送自定义消息,并在 Python 内核中安装自定义消息处理程序进行处理。在 IPEP-8 的“以前的工作”部分中链接了该方向的一些尝试:

https://github.com/ipython/ipython/wiki/IPEP-8:-Custom-messages-and-message-handlers#previous-work