Skip to content

Instantly share code, notes, and snippets.

@norweeg
Created July 29, 2022 20:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save norweeg/31e4f4bf76494bdbb102f07abee55d79 to your computer and use it in GitHub Desktop.
Save norweeg/31e4f4bf76494bdbb102f07abee55d79 to your computer and use it in GitHub Desktop.
Advanced Jupyter notebook export with nbconvert

Available Formats

nbconvert can convert to the following formats:

  • HTML
  • LaTeX
  • PDF
  • webPDF (equivalent to rendering as HTML and printing to PDF)
  • Reveal.js HTML slideshow
  • ascii
  • reStructuredText
  • python script
  • notebook

Executing notebook at export

You can make nbconvert execute your notebook before doing the export by using the --execute flag

jupyter nbconvert --execute --to <format> your_notebook.ipynb

This will execute your notebook non-interactively and convert it into your desired format. If you need to interact with your notebook (e.g. to provide input to something), open it in Jupyter to execute it, then save, then run the command without the --execute flag. If your notebook makes use of ipywidgets, make sure you have Settings > Save Widget State Automatically enabled. There are options for controlling what happens if your notebook execution results in an exception, or if it is hung up waiting for input. See the ExecutePreprocessor options in the documentation for more info.

Selectively omitting code cells

You can selectively hide cells using cell tags and using a pre-processor option to exclude cells with a matching tag. In JupyterLab, the cell metadata editor is on the right side of the UI and has an icon depicting two gears. Click to expand, then click "Add Tag". Add a tag e.g. "hide_input" then export your notebook with this:

jupyter nbconvert --execute --TagRemovePreprocessor.remove_input_tags hide_input --to <format> your_notebook.ipynb

There are similar options which lets you hide output or entire cells (i.e. input and output) with tags too.

Excluding code input cells altogether

You can also omit all code input cells at once with the --no-input flag

jupyter nbconvert --execute --no-input --to <format> your_notebook.ipynb

The result will be a publication-ready document without the code cells.

Clearing output from executed notebook in-place

This is useful as a git hook to clear output from a notebook prior to committing it in git

jupyter nbconvert --to notebook --inplace --clear-output *.ipynb

HTML with embedded images

Exporting to HTML with the --embed-images flag will base64-encode images in your notebook and embed them directly in the resulting HTML so the document renders correctly when shared

jupyter nbconvert --execute --to html --embed-images your_notebook.ipynb

HTML with toggles for code cells

The other file in this snippet is an nbconvert export template adapted from this gist which inherits from the built-in, default "lab" template for html exports. Specifying to use this template will produce output which looks like the standard html export, except all the code input cells will be collapsed and replaced by a button that shows/hides that code input cell.

jupyter nbconvert --execute --to html --template-file ./lab_with_toggle.html.j2 --embed-images your_notebook.ipynb

WebPDF

The plain PDF export format has a different look/feel than maybe what you were intending, resembling a LaTeX rendering compiled to PDF form (because that is literally how it is produced). The WebPDF format instead renders the notebook as HTML and then prints that to PDF. It supports options similar to both the HTML and PDF exporters. It uses chromium to render the HTML for printing, so you need to enable the option to allow it to download it for itself. I believe you need to have pyppeteer installed for this to work. conda install pyppeteer to install.

jupyter nbconvert --execute --to webpdf --allow-chromium-download  your_notebook.ipynb

CLI Documentation

For more information about nbconvert's CLI options, see its documentation

Bonus: Interactivity in static HTML (no Python kernel needed)

HTML exports of notebooks no longer have a Python kernel to process widget events or execute python code to provide new renders of plots. You can work around this by planning ahead. Plotting modules such as bokeh and plotly produce interactive plots using HTML and Javascript. Plotting module holoviews provides methods specifically for packaging rendered plots for exported HTML notebooks.

{% extends 'lab/index.html.j2' %}
{% block html_head %}
{{ super() }}
<script src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
crossorigin="anonymous"></script>
<script>
$(document).ready(function() {
$('.code_shower').on('click',function(){
var header = $(this);
var codecell = $(this).next()
codecell.slideToggle(0, function() {
if (codecell.is(':hidden')) {
header.text("Show Code");
header.css("border-radius", "2px 2px 2px 2px");
} else {
header.text("Hide Code");
header.css("border-radius", "2px 2px 0px 0px")
}
});
});
$('.hidden_default').next().hide();
});
</script>
<style>
div.input {
flex-direction: column !important;
}
div.input_area {
border-radius: 0px 0px 2px 2px;
}
div.code_shower {
background: lightgray;
padding: 5px 10px;
cursor: pointer;
border-radius: 2px 2px 0px 0px;
}
</style>
{% endblock html_head %}
{% block input %}
{% if 'code_shown' in cell['metadata'].get('tags', []) %}
<div class="code_shower">Hide Code</div>
{% else %}
<div class="code_shower hidden_default">Show Code</div>
{% endif %}
{{ super() }}
{% endblock input %}
{% block output_prompt %}
{% endblock output_prompt %}
{% block in_prompt %}
{% endblock in_prompt %}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment