Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

One-liner or short script to run the code inside a Jupyter notebook?

I like to develop scripts by running them piecemeal in a Jupyter (nee iJulia) notebook. However, sometimes I need to test things on a remote system and need to make a copy of just the code as a .jl file. Has anyone already written a one-liner or short script that runs the code in a .ipynb notebook? If not, I'll get to it at some point and post the code here.

like image 435
ARM Avatar asked Oct 31 '22 04:10

ARM


1 Answers

Here's what I have written up:

using JSON

get_code_cells(j::Dict) = filter(x->x["cell_type"] == "code", j["cells"])

function parse_code_cell(c::Dict)
    buf = IOBuffer()
    write(buf, "begin\n")
    map(x->write(buf, x), c["source"])
    write(buf, "\nend")

    src = bytestring(buf)
    parse(src)
end

extract_code(cells::Vector) = Expr[parse_code_cell(c) for c in cells]
extract_code(j::Dict) = extract_code(get_code_cells(j))
eval_code(j::Dict) = map(eval, extract_code(j))


# get filename, then parse to json, then run all code
const fn = ARGS[1]
eval_code(JSON.parsefile(fn))

It seems to work for many notebooks, but not everything. Specifically, it failed to run a notebook where I had

using PyCall
@pyimport seaborn as sns

When eval hit that chunk of code it complained about @pyimport not being defined (even though it is exported by PyCall).

If you are interested, we could definitely clean this up, add some more arguments and package it up into a proper command line utility.


EDIT

Now for something completely different...

This version shells out to ipython nbconvert, writes that to a temporary file, calls include on that temporary file to run the code, then deletes the temp file. This should be more robust (it passed examples the other one failed at). Same comments about cleaning/packaging apply.

const fn = abspath(ARGS[1])
dir = dirname(fn)

# shell out to nbconvert to get a string with code
src = readall(`ipython nbconvert --to script --stdout $fn`)

# Generate random filenamein this directory, write code string to it
script_fn = joinpath(dir, string(randstring(30), ".jl"))
open(script_fn, "w") do f
    write(f, src)
end

# now try to run the file we just write. We do this so we can make sure
# to get to the call `rm(script_fn)` below.
try
    include(script_fn)
catch
    warn("Failed executing script from file")
end

# clean up by deleting the temporary file we created
rm(script_fn)
like image 87
spencerlyon2 Avatar answered Nov 03 '22 00:11

spencerlyon2