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.
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.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With