Nbdev discussion

I’ve been a fan of literate programming since my first code with tangle and weave. I was always disappointed that it never gained traction. I hope nbdev gets closer to delivering on the promise of literate programming.

To that end, any pointers on how to import existing code and applications into nbdev and re-factoring it? Also any pointers on how to think about literate programming in the nbdev context. For example, when I was using cweb, I wrote the code is if I was writing a book. I started out with the beginning outline and the code segment referred to other fragments later in the narrative. . The beginning section will look something like


This little app takes a set of templates, one to a calendar event and data for each calendar event then expands them using recursive template expansion.

Make ENET monthly meeting blast

<Set up event iteration>
<for each event>
  <create template instance>
  <expand template>
  <generate time key>
  <sort header by skip>

The phrase between the <> characters refers to the section containing the detail and narrative. Every section could have a mixture of code and section references. Using my code base is an example, the first segment would be something like"

set up event iteration:
in order to iterate over the calendar events, gather up a list of event files, baseline template, and create dictionary with common data elements used in template expansion.
— Code section—

with open("event_template.rtmpl") as f:

common_dict = rTemplate.colon_parser("event_common", EOL=False)

event_dict = {}
nonevent_dict = {}

subsequent sections would fill in the detail outlined in the beginning and the tangle command would organize it in a compiler friendly order.

How do I reframe my literate programming experience to fit the nbdev model?

I think this is a thing with my anaconda maybe? I get similar errors when running the notebook 03_export2html from the nbdev repo. It says nbformat not installed, but it definitely is.

It’s likely, yes. Note that the import statements are added to execute all the show_doc cells in the notebook (it is then removed from the html). So it’s logical you have them during the doc building even if they were not in your original notebook.

I’ve only done that on a couple of small projects, by copying and pasting the docs into a notebook, and the modules, and then using “ctrl-shift-hyphen” to split into separate cells as appropriate. Then I move things around so that it makes sense.

It’s actually a very different mindset to cweb. cweb assumes you pretty much know what you want, and you can write it all out in a hierarchical top-down way. nbdev assumes you don’t really know what you’re doing, and you build it up from little pieces step by step.

The best way to understand this mindset is to look at the nbdev and fastai2 source nbs.

I’ll be interested to hear how it works out for you!

First bit of trouble and having is that exploring nbdev is seriously cutting into my sleep. I was awake till 4 AM yesterday playing with it. Damn you, damn you all to hell… :rofl: I apologize for the chaotic nature of these questions. I am asking questions stream of consciousness and I’m clearly missing some very basic knowledge about Jupyter notebooks.

I appreciate your patience and responses.

One thing that tangle/weave did was it allowed you to order the narrative based on its needs, not what the compiler requires. That is really important for writing literate code. However, deviating significantly from the order the compiler needs reduces ability to debug. The debug issue would not exist if one could debug code using the literate form and not the tangled form.

Moving on to specific examples. 00 export creates lots of questions.

Why you have a number prefix on all of the sections (00_export, 00_sync etc.)? I am guessing that ordering is important and the easiest/fastest way of doing this is to use lexical sorting of filenames. The number prefix gives you easy and explicit control independent of a configuration file.

The second and third blocks have some sort of control information and a hidden import. Elaborate please?

Section export to modules/basic foundations is a bit of a mystery. I’m assuming it is in line code executed when the file is loaded/imported. Don’t understand why it’s there or how it gets used.

Show_doc is defined where? Why is there a <IPython.core.display.Markdown object> after the code fragment, apparently hanging out in the block with no apparent connection to anything? Is <IPython.core.display.Markdown object> telling the notebook how to display/publish the documentation extracted by show_doc?

Section reading a notebook is the first bit of code I’ve seen that ends up in the export.py file. Now it starts to make sense and I can see how the blocks end up in the tangled file.

Now I get confused again because I went and looked at the docs directory.

Why are there absolute URLs in index.html,
why are the docs directory contents half HTML but not the same as the live website?

Then there is another disconnect between notebook contents and the matching documentation page. In the notebook, you define read_nb but it’s not defined in the documentation, only reference to the function definition.

Having test code adjacent to the definition makes a lot of sense but in the documentation seems out of context because of missing information.

Yeah there’s a lot of things I don’t understand why they’re visible sometimes and not visible others. For example the regular expression statements are not visible but the block with assertions in it is.

I’m in stop here. I need to get some sleep but if there’s something basic about Jupyter notebooks that I need to know. Tell me where to look for the docs and I will read up before asking more questions

Ok solved by doing this in the nbs directory:

ln -s /home/marco/miniconda3/envs/TEST/lib/python3.7/site-packages/* .

And also modify .gitignore:

# Ignore the symlinks in the nbs folder, but include the notebooks

But then why does the build libs work? Is build docs called in a different way?

Anyway, for now this will be fine, now I can start building stuff using this awesome tool :smiley: because one of the main reasons I want to use it is because I have never in the past managed to write proper documentation and it ends up all over the place


I don’t understand your question. To build the docs, the library you’re building must be accessible somewhere (at least in the notebook folder with a simlink)

It’s an error with my anaconda, it’s picking up libraries from an ancient conda environment, have no idea why. Apologies to waste your time on this one :no_mouth:


They’re not particularly important, but we find it very helpful to see/show the order things were built, so that you can read from the start if you want to do a deep dive into the code.

Most of your questions are answered in the docs, which are here: http://nbdev.fast.ai/ . I’ll answer a couple here that may be less obvious. Feel free to follow up if you can’t find answers though.

It means the notebook isn’t trusted. That happens automatically if you run nbdev_install_git_hooks after you clone. Otherwise click File->Trust in the notebook itself.

The website is jekyll. GitHub Pages automatically converts it for you. If you use something else to host, then you’ll need to build with jekyll yourself.

Remember in the nbdev dir you have a complete python project, so you can navigate using tags and/or your preferred editor/IDE. You can also type doc(show_doc), which pops up a window containing a link to the source on GitHub. Or type nb_source_link(show_doc) for a link to the notebook that defined it.

Bug(?) tqdm Output in Docs Not Rendering

Firstly, thank you for nbdev, it’s been a very empowering tool.

When I build docs with nbdev_build_docs, the part of my notebook with tqdm output doesn’t render as expected. It saves space for the tqdm output but renders it blank.

This is probably not an issue with nbdev because the same issue occurs when I export the notebook to html via the toolbar in the notebook, but I thought this is worth mentioning anyways.


nbdev Generated Doc:

Native Export to HTML:

All widgets are removed from the outputs for the docs, not sure what tqdm produces, but is i’t s a widget and not HTML content (like fastprogress), it’s probably why it’s not rendered. You could use the console version to get the outputs.



What @sgugger meant to say, I think is: don’t use tqdm, use fastprogress! :wink:

1 Like

Really excited to try all the new features. Anything that I had a complaint about re: nb development seems to be addressed here. Also really incredible that you all were able to develop several groundbreaking libraries simultaneously.

Mini Bug Report: It seems like the katek isn’t rendering properly in the nbdev docs.

Mini Bug #2: Settings.ini from nb_dev template is generated with


but should be


I fixed mini bug 2 (note that when you point an issue and give the solution, you can just do a PR instead :wink: ). For mini bug 1, @jeremy you might be more useful then me since you were the one to add that support.

1 Like

Sure thing, will do in future. Would’ve PR’d but I remembered jeremy saying at some point that sometimes it’s easier for you guys to make small fixes than deal with outside PRs.

Speaking of PRs for nbdev, how do you guys generally navigate your notebooks? Would auto generated table of contents/links based on header hierarchy be useful?

Yes, and it’s already available as the ‘toc2’ extension :slight_smile:

1 Like

Working for me

Maybe you’re blocking the js or something?..

1 Like

Working for me now as well. Guess we don’t have to worry about it :grin:

There is a small problem with the Github Actions on the template causing the Check if there is no diff library/notebooks step to silently fail. I did a PR to fix it here.

Edit: Should I also PR this change in the other fastai repositories that are affected by it?

1 Like