.. versionadded:: 4.2 You can now use the ``--to`` flag to use custom export formats defined outside nbconvert.
The command-line syntax to run the nbconvert
script is:
jupyter nbconvert --to FORMAT notebook.ipynb
This will convert the Jupyter document file notebook.ipynb
into the output
format designated by the FORMAT
string as explained below.
A few built-in formats are available by default: html
, pdf
, webpdf
,
script
, latex
. Each of these has its own exporter with many
configuration options that can be extended. Having the option to point to a
different exporter allows authors to create their own fully customized
templates or export formats.
A custom exporter must be an importable Python object. We recommend that these be distributed as Python libraries.
Additional exporters may be registered as named entry_points.
nbconvert uses the nbconvert.exporters
entry point to find exporters
from any package you may have installed.
If you are writing a Python package that provides custom exporters, you can register the custom exporters in your package's :file:`setup.py`. For example, your package may contain two custom exporters, named "simple" and "detail", and can be registered in your package's :file:`setup.py` as follows:
setup(
# ...
entry_points={
"nbconvert.exporters": [
"simple = mymodule:SimpleExporter",
"detail = mymodule:DetailExporter",
],
}
)
Now people who have installed your Python package containing the two custom exporters can call the entry point name:
jupyter nbconvert --to detail mynotebook.ipynb
instead of having to specify the full import name of the custom exporter.
We encourage registering custom exporters as entry points as described in the
previous section. Registering a custom exporter with an entry point simplifies
using the exporter. If a custom exporter has not been registered with an
entry point, the exporter can still be used by providing the fully qualified
name of this exporter as the argument of the --to
flag when running from
the command line:
$ jupyter nbconvert --to <full.qualified.name of custom exporter> notebook.ipynb
For example, assuming a library tcontrib
has a custom exporter name
TExporter
, you would convert to this custom format using the following:
$ jupyter nbconvert --to tcontrib.TExporter notebook.ipynb
A library can contain multiple exporters. Creators of custom exporters should make sure that all other flags of the command line behave the same for the custom exporters as for built-in exporters.
An external exporter can control almost any parameter of the notebook conversion process, from simple parameters such as the output file extension, to more complex ones such as the execution of the notebook or a custom rendering template.
All external exporters can expose custom options using the traitlets
configurable API. Refer to the library that provides these exporters for
details on how these configuration options works.
You can use the Jupyter configuration files to configure an external exporter. As
for any nbconvert
exporters you can use either the configuration file syntax of
c.MyExporter.config_option=value
or the command line flag form
--MyExporter.config_option=value
.
Under the hood exporters are python classes that expose a certain interface. Any importable classes that expose this interface can be use as an exporter for nbconvert.
For simplicity we expose basic classes that implement all the relevant methods that you have to subclass and overwrite just the relevant methods to provide a custom exporter. Below we show you the step to create a custom exporter that provides a custom file extension, and a custom template that inserts before and after each markdown cell.
We will lay out files to be ready for Python packaging and distributing on PyPI, although the exact art of Python packaging is beyond the scope of this explanation.
We will use the following layout for our package to expose a custom exporter:
mypackage ├── LICENSE.md ├── setup.py └── mypackage ├── __init__.py └── templates └── test_template.tpl
If you wished to create this same directory structure you could use the following commands
when you are at the directory under which you wish to build your mypackage
package:
mkdir -p mypackage/mypackage/templates
touch mypackage/LICENSE.md
touch mypackage/setup.py
touch mypackage/mypackage/__init__.py
touch mypackage/mypackage/templates/test_template.tpl
Important
You should not publish this package without adding content to your LICENSE.md
file.
For example, nbconvert
follows the Jupyter Project convention of using a Modified BSD
License (also known as New or Revised or 3-Clause BSD).
For a guide on picking the right license for your use case,
please see choose a license.
If you do not specify the license, your code may be unusable by many open source projects.
As you can see the layout is relatively simple, in the case where a template is not needed we would actually have only one file with an Exporter implementation. Of course you can change the layout of your package to have a more fine-grained structure of the subpackage. But lets see what a minimum example looks like.
We are going to write an exporter that:
- exports to html, so we will reuse the built-in html exporter
- changes the file extension to
.test_ext
# file __init__.py
import os
import os.path
from traitlets.config import Config
from nbconvert.exporters.html import HTMLExporter
# -----------------------------------------------------------------------------
# Classes
# -----------------------------------------------------------------------------
class MyExporter(HTMLExporter):
"""
My custom exporter
"""
# If this custom exporter should add an entry to the
# "File -> Download as" menu in the notebook, give it a name here in the
# `export_from_notebook` class member
export_from_notebook = "My format"
def _file_extension_default(self):
"""
The new file extension is ``.test_ext``
"""
return ".test_ext"
@property
def template_paths(self):
"""
We want to inherit from HTML template, and have template under
``./templates/`` so append it to the search path. (see next section)
Note: nbconvert 6.0 changed ``template_path`` to ``template_paths``
"""
return super().template_paths + [
os.path.join(os.path.dirname(__file__), "templates")
]
def _template_file_default(self):
"""
We want to use the new template we ship with our library.
"""
return "test_template" # full
And the template file, that inherits from the html full
template and prepend/append text to each markdown cell (see Jinja2 docs for template syntax):
{% extends "full.tpl" %} {% block markdowncell -%} ## this is a markdown cell {{ super() }} ## THIS IS THE END {% endblock markdowncell %}
Assuming you install this package locally, or from PyPI, you can now use:
jupyter nbconvert --to mypackage.MyExporter notebook.ipynb