2016-08-09 32 views
2

我創建了龍捲風服務器,它接受python和matlab代碼並執行它。這是服務器代碼。如何在這種情況下使用龍捲風協程?

from zmq.eventloop.zmqstream import ZMQStream 
from zmq.eventloop import ioloop 
ioloop.install() 

from functools import partial 
from tornado import web, gen, escape 
from tornado import options, httpserver 
from tornado.concurrent import Future 

settings = dict() 
settings['autoreload'] = True 
settings['debug'] = True 

from jupyter_client import MultiKernelManager 

reply_futures = {} 
kids = [] 

class MainHandler(web.RequestHandler): 
    def get(self): 
     self.write("Hello") 

class ExecuteHandler(web.RequestHandler): 
    def get(self): 
     self.write("approaching execute") 

    def post(self): 
     data = escape.json_decode(self.request.body) 
     print data 
     self.application.execute_code(data) 

class Application(web.Application): 

    def __init__(self): 

     handlers = [] 
     handlers.append((r"/", MainHandler)) 
     handlers.append((r"/execute", ExecuteHandler)) 
     web.Application.__init__(self, handlers, **settings) 
     self.km = MultiKernelManager() 
     self.setup_kernels() 

    def setup_kernels(self): 

     matlab_kernel_id = self.km.start_kernel(kernel_name="matlab") 
     python_kernel_id = self.km.start_kernel(kernel_name="python") 

     self.matlab_kernel_id = matlab_kernel_id 
     self.python_kernel_id = python_kernel_id 

     matkab_kernel_client = self.km.get_kernel(matlab_kernel_id).client() 
     matkab_kernel_client.start_channels() 

     python_kernel_client = self.km.get_kernel(python_kernel_id).client() 
     python_kernel_client.start_channels() 

     self.matkab_kernel_client = matkab_kernel_client 
     self.python_kernel_client = python_kernel_client 

     matlab_iopub_stream = ZMQStream(matkab_kernel_client.iopub_channel.socket) 
     matlab_shell_stream = ZMQStream(matkab_kernel_client.shell_channel.socket) 

     python_iopub_stream = ZMQStream(python_kernel_client.iopub_channel.socket) 
     python_shell_stream = ZMQStream(python_kernel_client.shell_channel.socket) 

     matlab_iopub_stream.on_recv_stream(partial(self.reply_callback, matkab_kernel_client.session)) 
     matlab_shell_stream.on_recv_stream(partial(self.reply_callback, matkab_kernel_client.session)) 

     python_iopub_stream.on_recv_stream(partial(self.reply_callback, python_kernel_client.session)) 
     python_shell_stream.on_recv_stream(partial(self.reply_callback, python_kernel_client.session)) 

    def reply_callback(self, session, stream, msg_list): 
     idents, msg_parts = session.feed_identities(msg_list) 
     reply = session.deserialize(msg_parts) 

     if "stream" == reply["msg_type"]: 
      print reply["content"]["text"] 
     parent_id = reply['parent_header'].get('msg_id') 
     reply_future = reply_futures.get(parent_id) 
     if reply_future: 
      reply_future.set_result(reply) 

    def execute_code(self, data): 

     matlab_code = data['matlab_code'] 
     python_code = data['python_code'] 

     self.execute_matlab_then_python(matlab_code, python_code) 

    @gen.coroutine 
    def execute_matlab_then_python(self, matlab_code, python_code): 

     print "executing matlab code" 
     parent_id1 = self.matkab_kernel_client.execute(matlab_code) 
     f1 = reply_futures[parent_id1] = Future() 
     yield f1  

     print "executing python code" 
     parent_id2 = self.python_kernel_client.execute(python_code) 
     f2 = reply_futures[parent_id2] = Future() 
     yield f2 

    def shutdown_kernels(self): 
     self.km.get_kernel(self.matlab_kernel_id).cleanup_connection_file() 
     self.km.shutdown_kernel(self.matlab_kernel_id) 

     self.km.get_kernel(self.python_kernel_id).cleanup_connection_file() 
     self.km.shutdown_kernel(self.python_kernel_id) 

if __name__ == '__main__': 

    options.parse_command_line() 
    app = Application() 
    server = httpserver.HTTPServer(app) 
    server.listen(8888) 

    try: 
     ioloop.IOLoop.current().start() 
    except KeyboardInterrupt: 
     print 'going down' 
    finally:  
     app.shutdown_kernels() 

我用它來訪問的客戶端代碼,這裏

import json 
import requests 

matlab_code = "a=magic(3);disp(a)" 
python_code = "print 'Hello World!!'" 

data = {} 
data['matlab_code'] = matlab_code 
data['python_code'] = python_code 

r = requests.post('http://0.0.0.0:8888/execute', json.dumps(data)) 

我關心的是保持執行的順序,以使MATLAB完成後,才Python代碼得到執行。我使用jupyter_client來執行matlab/python代碼。我在這裏使用python27。問題是,當我提交代碼時,它會拋出TypeError: 'NoneType' object is not iterable。這是一個堆棧跟蹤它。

 
[E 160809 15:17:51 ioloop:633] Exception in callback None 
    Traceback (most recent call last): 
     File "/usr/local/lib/python2.7/dist-packages/tornado/ioloop.py", line 887, in start 
     handler_func(fd_obj, events) 
     File "/usr/local/lib/python2.7/dist-packages/tornado/stack_context.py", line 275, in null_wrapper 
     return fn(*args, **kwargs) 
     File "/usr/local/lib/python2.7/dist-packages/zmq/eventloop/zmqstream.py", line 440, in _handle_events 
     self._handle_recv() 
     File "/usr/local/lib/python2.7/dist-packages/zmq/eventloop/zmqstream.py", line 472, in _handle_recv 
     self._run_callback(callback, msg) 
     File "/usr/local/lib/python2.7/dist-packages/zmq/eventloop/zmqstream.py", line 414, in _run_callback 
     callback(*args, **kwargs) 
     File "/usr/local/lib/python2.7/dist-packages/tornado/stack_context.py", line 275, in null_wrapper 
     return fn(*args, **kwargs) 
     File "/usr/local/lib/python2.7/dist-packages/zmq/eventloop/zmqstream.py", line 191, in 
     self.on_recv(lambda msg: callback(self, msg), copy=copy) 
     File "tornado_test.py", line 86, in reply_callback 
     reply_future.set_result(reply) 
     File "/usr/local/lib/python2.7/dist-packages/tornado/concurrent.py", line 276, in set_result 
     self._set_done() 
     File "/usr/local/lib/python2.7/dist-packages/tornado/concurrent.py", line 320, in _set_done 
     for cb in self._callbacks: 
    TypeError: 'NoneType' object is not iterable 

我不明白這裏有什麼問題?

+0

將代碼的所有相關部分放在這裏會讓你的問題對其他人有幫助,因爲鏈接和存儲庫可能會失效。 –

回答

1

不幸的是,神祕的錯誤消息「'NoneType'對象不可迭代」意味着您在同一個Future對象上多次呼叫set_result。我對zmq或jupyter內核接口知之甚少,但我的猜測是,兩種不同內核的execute方法返回的ID是重疊的,或者每個執行調用獲得多個響應(來自兩個不同的流?)。