发送meesage时,无法从jupyter zmq频道获取返回执行结果

时间:2016-05-11 08:19:42

标签: python jupyter jupyter-notebook

当我尝试使用python代码连接到它的jupyter客户端时,我遇到了一个问题。

在jupyter的源代码中,在打开websocket时建立了与zmq通道的连接

def open(self, kernel_id):
    super(ZMQChannelsHandler, self).open()
    try:
        self.create_stream()
    except web.HTTPError as e:
        for channel, stream in self.channels.items():
            if not stream.closed():
                stream.close()
        self.close()
    else:
        for channel, stream in self.channels.items():
            //this is callback function when receive message from zqm channel
            stream.on_recv_stream(self._on_zmq_reply) 

在create_stream函数中,zmq通道已建立。

def create_stream(self):
    km = self.kernel_manager
    identity = self.session.bsession
    for channel in ('shell', 'iopub', 'stdin'):
        meth = getattr(km, 'connect_' + channel)
        self.channels[channel] = stream = meth(self.kernel_id, identity=identity)
        stream.channel = channel
        ... ignore no significance code

当服务器收到消息时,on_message被调用

def on_message(self, msg):
    if not self.channels:
        return
    if isinstance(msg, bytes):
        msg = deserialize_binary_message(msg)
    else:
        msg = json.loads(msg)
    channel = msg.pop('channel', None)
    if channel is None:
        channel = 'shell'
    if channel not in self.channels:
        return
    stream = self.channels[channel]
    self.session.send(stream, msg)

此时,zmq通道接收要执行的python代码。之后,执行结果应该返回,因此应该调用上面的on_recv_stream函数,最后得到结果。

所以我写这样的python代码片段:

from jupyter_client.multikernelmanager import MultiKernelManager
from jupyter_client.session import Session

from tornado import gen, web
from tornado.concurrent import Future
from tornado.ioloop import IOLoop

km = MultiKernelManager()

kernelid = km.start_kernel()

kernel =km.get_kernel(kernelid)

channel =  km.connect_shell(kernelid)

print 'channel', channel


def on_reply(msg):
    print 'we got return'

def on_timeout():
    print("Timeout waiting for kernel_info_reply: %s", kernel_id)

kernel.session.send(channel, 'kernel_info_request')
channel.on_recv(on_reply)

实际上,我没有收到返回消息,也就是说,没有调用on_reply函数。我没有问题是什么,任何人都可以帮助我吗?

1 个答案:

答案 0 :(得分:0)

我解决了这个问题:

from jupyter_client.multikernelmanager import MultiKernelManager


km = MultiKernelManager()

kernelid = km.start_kernel('python2')

kn =km.get_kernel(kernelid)

kc = kn.client()

kc.start_channels()

msg_id = kc.execute('import math\nprint(math.sqrt(2))')

while True:
try:
    msg = kc.get_iopub_msg()
    print('\niopub msg is')
    print(msg)
except Excption,e:
    print(e)
    break

if msg['parent_header'].get('msg_id') != msg_id:
    continue

msg_type = msg['msg_type']
content = msg['content']

print('content is :')
print(content)

if msg_type == 'status':
    if content['execution_state'] == 'idle':
        break
    else:
        continue