ipython/ipynb

Make IPython Magics work

yuvipanda opened this issue · 5 comments

Currently, we don't support IPython Magics at all from noteboks. We initially supported them, but removed them because importing IPython was causing a massive startup time lag (>1s) that seemed pretty bad.

Ideally, I'd like to be able to do the following:

  1. If IPython is already loaded (you are already in a notebook), support magics by default
  2. If IPython is not loaded, and there are no magics in the imported notebooks, do not load it
  3. Load IPython only if there are magics in the notebook

I'd also like to possibly consider implementing the ! action (which runs things in a shell) natively, so we don't have to import all of IPython to get just that behavior. Also investigate why startup takes so long!

A simpler solution that I would be 100% happy with would be just to ignore magics. Currently I get:

File "<unknown>", line 15
    %matplotlib inline
    ^
SyntaxError: invalid syntax

I would also like to just ignore magic commands. Usually I only use %matplotlib inline and %timeit.

In my use case I only want to import function definitions. I would prefer that all other code cells be skipped

I am happy to define my functions in separated cells to make it easier for the parser

I use %matplotlib and %timeit a lot.

I also get the same error when using "!"
for example: "!pip"

So this isn't a direct solution but maybe a step forward. Since magics are usually applied at the "cell" level it might be worth considering importing "cells" instead of just functions. If that's the case then you can use something like this

from IPython.lib.kernel import get_connection_file
from jupyter_client import BlockingKernelClient

def import_cell(notebook_path, cell_number):

    ## Read notebook
    notebook_file = open(notebook_path)
    nb = nbformat.read(notebook_file,as_version=4)

    ## Creat kernel client on current
    ## running kernal
    client = BlockingKernelClient()
    client.load_connection_file(get_connection_file())
    client.start_channels()

    ## Execute code cell
    nb_code_cells = [c for c in nb.cells if c["cell_type"] == "code"]
    client.execute(code_cells[cell_number].source)

import_cell("path/to/notebook.ipynb", 0)

To "import" (really it just executes the cell in your current ipython kernel). But if users want to import cells by cell tag they could do something like

from ipynb.fs.cells.my_notebook import my_cell_tag

Where the cell tag could be searched for in the metadata across the notebook