Skip to content
Andrew Ray edited this page Feb 20, 2014 · 1 revision

IPython

This is my best guess for how things works in IPython.

There are three main things involved when IOcaml starts.

  • Notebook - runs a user interface and talks over websockets to IPython.
  • IPython - runs the webserver. All communications between IOCaml and the notebook go through IPython.
  • IOCaml - talks to IPython through ZeroMQ messages. IPython also sends signals to IOCaml in certain cases.

I am a little unsure exactly how much work IPython is doing apart from being a webserver and a bridge for messaging.

IOCaml

IOCaml needs to run the REPL, respond to messages from the notebook and generate messages back to the notebook. The very first version of IOCaml did this;

  1. Wait for code execution message from the notebook.
  2. Run the code.
  3. Collect up all the responses (from stdout, stderr and the compiler messages) and send them to the notebook.

I soon noticed an issue - if you write a few Kb to stdout the REPL will lockup on the next write. A fair enough point, the out_channel is buffered and full. So, we need to run I/O concurrently with code execution.

This is possible because user code I/O and kernel messages are run on different zeromq sockets. There are basically two important sockets here shell and iopub. The shell socket mainly controls code execution (and IOCaml). The iopub socket deals with all the responses.

What we do is start a thread to deal with the iopub socket. The main thread just deals with shell messages. The two threads communicate through Marshalled messages over a Unix.pipe.

There is still a distinct execution flow going on;

  1. shell gets a message and starts running user code.
  2. iopub gets messages from user code (ie send_mime) and monitors stdout and stderr for activity and sends messages to the notebook for display.
  3. The code finishes. iopub is told to flush. The notebook is told we are done.
  4. Repeat.
Clone this wiki locally