In this blog post, I present an idea for remote workshops, which make strong, interactive use of Jupyter Notebooks to teach content: let’s call it for now “discreet assistance”.


The context I am working in is the data-driven analysis of software systems: Software Analytics. Back then, at the time of offline workshops on Software Analytics, I covered large parts with interactive programming exercises. Using Jupyter Notebook and available online platforms like, the technical possibilities are vast. In the workshop, I first introduce the basics of Jupyter Notebook (e. g. the idea, functionality and most important shortcuts), and then I do a small analysis task together with the participants. Here, participants will learn the syntax of Python and pandas and how to apply is at the same time (and much more, which, among others, happens to be in the guide “Teaching and Learning with Jupyter”, which I got to know a few days ago. Great resource!). If something doesn’t work out, I’ll go into detail again at offline events instant and on-demand. With this approach, I get direct feedback during the interactive parts of the workshop.

Context Switch

COVID-19. No more on-site workshops! Although I partly miss traveling and on-site workshops, remote workshops work surprisingly well. I like Miro, for example, very much to involve participants interactively. This has certain parallels to the offline workshops with Jupyter Notebook. But it’s the latter that worries me: the direct feedback channel is no longer there. Moreover, in online video conferences, participants are (it seems to me) also a bit shy when support is needed.

So I was looking for a way to help participants discreetly with interactive Jupyter Notebook exercises without compromising the ease of use of Jupyter Notebook. Together with the online video conference Zoom, I am now pursuing the concept of “discreete assistance” in remote workshops: Participants can engage in the joint analysis tasks and discussions, but always can uncover a possible solution in the notebooks to follow along. Should complications arise, they will have assistance at hand. The following animation gives you an impression how it works:


Discreet assistance in Jupyter Notebook


So how does this work? To be honest, it’s a big hack! I used the Unofficial Jupyter Notebook Extensions, a creative way to configure some of its extensions and a little Python script for some magic. Let me take you through the main ideas.

Instructor’s notebook

Because I’m lazy thriving for efficiency, I have one leading notebook with a possible solution to the presented software data analysis. I then convert this notebook in the executed version to a special version. There are two things you have to do in your instructor’s notebook:

  1. mark the cell with the code (or markdown text, in the case that you want to display an answer instead of code/results) with a special tag (I’ve called this tag “delete”)
  2. Make a subsequent cell a markdown cell with a heading

Extensions’ configuration

In a minimal configuration, you’ll need two Jupyter Notebook extensions, which “creative” configuration:

Collapsible Headings

The Collapsible Headings extension allows you to collapse cells that have a markdown heading on top. Text in the cell itself will not collapse, but all the following cells that don’t have a markdown heading on the top.

The Collapsible Headings extension in action


I personally didn’t liked all the other down-facing arrows in the notebook because I found them distracting. So I deleted the entry of “font-awesome class for the toggle control icon on uncollapsed (expanded) headings” in the Collapsible Headings configuration.


The other extension that is needed is “Freeze”. You can tell Jupyter Notebook not to execute the specific cells and make cells read-only by freezing. For aesthetic reasons, I’ve just changed the color of the frozen code cell’s background to green to make a solution cell better visible.

Both extensions just must be activated and configured. The reminder will be addressed by a little (ugly) Python script.

The Python Script

This is the little helper script I’m currently using to do the magic (please just fly over it. I’ll explain it after the code block; feedback and improvement suggestions very welcome!):

It does mainly two things:

  1. Make a copy of the instructor’s notebook for the participants
  2. Put the code cells and their results under a markdown cell with a heading named “SOLUTION” (+ some explaining text)

To avoid work for me as an instructor, the hiding and freezing of cells is done directly with the script. The script is a little bit longer because it works with two kinds of discreet assistance circumstances: code cells (with solution code and displayed results) and markdown cells (with formatted text as result).

In both cases, we need a preceding, new cell (named solution_markdown_cell) that begins with a markdown heading on top to use the Collapsible Headings feature. This cell is also set to “hidden” (=collapsed) so that participants don’t see the subsequent cells (until the next markdown heading). This cell setting enables the participant to click on the little arrow next to the cell to see the answer.

Bonus: the arrow on the left side disappears, so participants can’t switch back. I think this side effect is a good self-motivational challenge for participants to unlock as few solutions as possible in a notebook.

Further, in the script, there is a different treating for markdown cells and code cells. Markdown cells contain possible answers to questions that are in the notebook. They are just inserted after the solution_markdown_cell and therefore hidden in the participant’s version of the notebook.

The code cells are treated a little differently because, besides the markdown cell with the solution heading, we also need an empty cell for the participant’s code. So the original cell is deep-copied to have a solution_code_cell. The solution_code_cell is frozen and is placed under the empty cell. The original cell is then emptied and added to the notebook, followed by the solution_markdown_cell and the solution_code_cell.

All other cells (which don’t have the “delete” tag set) are added as they appear in the notebook’s list of cells as well.

Finally, for aesthetic reasons, the execution_count is set to None for all cells.

The script writes the data then back to the new participant’s version of the file.



I hope I could explain the reasons and the implementation of my discreet assistance approach. I deliberately avoided using grading systems because I think I have a slightly different use case. If you know any alternative solutions for interactive remote Jupyter Notebook sessions, please let me know.


An here is a video that shows the solution in action in a remote workshop setting:

Video demonstrating the discreet assistance feature

Discreet Assistance in Jupyter Notebook

Leave a Reply

Your email address will not be published. Required fields are marked *

I accept that my given data and my IP address is sent to a server in the USA only for the purpose of spam prevention through the Akismet program.More information on Akismet and GDPR.