class Kernel(object): def __init__(self): # kernel config is stored in a temp file config = os.path.join(tempfile.gettempdir(), "kernel-%s.json" % str(uuid.uuid4())) args = [sys.executable, '-m', 'IPython', 'kernel', '-f', config] p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # when __this__ process exits, we're going to remove the ipython config # file and kill the ipython subprocess atexit.register(p.terminate) def remove_config(): os.remove(config) atexit.register(remove_config) # i found that if i tried to connect to the kernel immediately, it wasn't up # and running. 1.5 seconds was arbitrarily chosen (but seems to work) time.sleep(1.5) # fire up the kernel with the appropriate config self.client = BlockingKernelClient(connection_file=config) self.client.load_connection_file() self.client.start_channels() # load our monkeypatches... self.client.execute(matplotlib_patch) self.client.execute(autocomplete_patch) self.client.execute(vars_patch) def _run_code(self, code, timeout=0.1): # this function executes some code and waits for it to completely finish before # returning. i don't think that this is neccessarily the best way to do this, but # the IPython documentation isn't very helpful for this particular topic. # # 1) execute code and grab the ID for that execution thread # 2) look for messages coming from the "iopub" channel (this is just a stream of output) # 3) when we get a message that is one of the following, save relevant data to `data`: # - execute_result - content from repr # - stream - content from stdout # - error - ansii encoded stacktrace # the final piece is that we check for when the message indicates that the kernel is idle # and the message's parent is the original execution ID (msg_id) that's associated with # our executing code. if this is the case, we'll return the data and the msg_id and exit msg_id = self.client.execute(code) data = None while True: try: reply = self.client.get_iopub_msg(timeout=timeout) except Empty: continue if "execution_state" in reply['content']: if reply['content']['execution_state']=="idle" and reply['parent_header']['msg_id']==msg_id: if reply['parent_header']['msg_type']=="execute_request": return { "output": data, "msg_id": msg_id } elif reply['header']['msg_type']=="execute_result": data = reply['content']['data']['text/plain'] elif reply['header']['msg_type']=="stream": data = reply['content']['text'] elif reply['header']['msg_type']=="error": data = "\n".join(reply['content']['traceback']) def execute(self, code): return self._run_code(code) def complete(self, code): # i couldn't figure out how to get the autocomplete working with the ipython # kernel (i couldn't get a completion_reply from the iopub), so we're using # jedi to do the autocompletion. the __autocomplete is defined in `autocomplete_patch` # above. return self.execute("__autocomplete('%s')" % code)
from IPython.kernel import BlockingKernelClient, get_connection_file, find_connection_file cf= find_connection_file("kernel-305.json") client = BlockingKernelClient(connection_file=cf) client.load_connection_file() client.start_channels() client.execute('ddd') msg = client.get_shell_msg(block=True, timeout=3000) print msg