有没有办法在google.colab.kernel.com.ms对象上注册消息处理程序回调



advanced_outputs.ipynb中从内核向客户端发送数据的示例几乎正是我所需要的。这个例子引用了Jupyter的通信文档。但是,目前,尽管我可以从附加了数据的内核打开与客户端的新连接,但我还不能通过同一连接发送多条消息,这是对的吗?

我想我想要的工作流程是,例如,在javascript:中

(async () => {
google.colab.kernel.comms.registerTarget('example_comms', (comm, message) => {
document.body.appendChild(document.createTextNode('comm opened.'))
comm.send('comm opened');
console.log(comm)
comm.on_msg(function(msg) {
var p = document.createElement("p")
var t = document.createTextNode(message.data.foo)
p.appendChild(t)
document.body.appendChild(p)
})
});
})()

和在python 中

channel = comm.Comm(target_name='example_comms')
def handle_message(msg):
print(f"python received message: {msg['content']['data']}")
channel.on_msg(handle_message)
for i in range(10):
channel.send(data={'foo': i})

但谷歌实验室kernel.comms.Comm似乎没有导出on_msg,也没有任何其他我可以看到的在同一频道上发送多条消息的方式?ipykernel.comm.Comm对象有一个send方法,但我认为目前不能使用它?

这是一个对advanced_outputs示例进行了最小修改的笔记本。运行它会在控制台中引发未定义on_msg的错误。

我怀疑(但无可否认,我还没有衡量性能来确认(为每条消息建立新的连接是我想要避免的开销。感谢您的帮助!

我想这就是您想要的:

from IPython.display import Javascript
comm_ = None
def target_func(comm, msg):
global comm_
comm_ = comm  # The connection you are looking for !
## Register handler for later messages
@comm.on_msg
def _recv(msg):
# Use msg['content']['data'] for the data in the message
comm.send({'echo': msg['content']['data']})

@comm.on_close
def _close(msg):
global comm_
comm_ = None
get_ipython().kernel.comm_manager.register_target('comm_target', target_func)
Javascript('''
(async () => {
const channel = await google.colab.kernel.comms.open('comm_target');
(async function() {
for await (const message of channel.messages) {
console.log(message.data)
}
})();
})()
''')

与您正在做的相反,它正在建立一个从客户端到内核的通信通道,在我看来这更自然。此时,您将获得一个持久连接comm_,可以使用它向javascript前端发送消息:

comm_.send(data="test")

还可以获得每个打开连接的列表:

get_ipython().kernel.comm_manager.comms

因此,可以去掉丑陋的全局var,并监视更改的这个属性。例如,它也可以用于等待建立连接。

请注意,在Jupyter Notebook的情况下,Python代码是相同的,但不是Javascript代码。以下是相应的实现:

const channel = await Jupyter.notebook.kernel.comm_manager.new_comm('comm_target')
channel.on_msg(function(message) {
console.log(message.content.data);
});

最新更新