Format a Jupyter notebook on save in VSCode

Question:

I use black to automatically format all of my Python code whenever I save in VSCode. I’d like the same functionality, but within a Jupyter notebook in VSCode.

This answer shows how to right click and format a cell or a whole notebook from the right click context menu, or a keyboard shortcut. Can I make this happen on save instead?

It looks like there is an issue related to this, but it is over a year old.

Are there any good workarounds? Maybe a way to set the format notebook option to the same keybinding as save?

UPDATE:

If you like me want this functionality to be added please go to the issue and upvote it, the devs said they will need a bunch of upvotes before it’s considered.

Asked By: Salvatore

||

Answers:

There are no plans yet according to Github.

Answered By: MingJie-MSFT

This is not officially supported, but there could be workarounds.

From janosh’s reply on GitHub:

There is a setting editor.codeActionsOnSave but it doesn’t allow running arbitrary shell commands (for security reasons?) so you’d need to install an extension like Run On Save and get it to call black path/to/file.ipynb on save events.

Sadly even that doesn’t work right now since VS Code does not yet expose lifecycle events for notebooks. The issue to upvote for that is: Improve workspace API for Notebook lifecycle to support (at least) saving events

If both get implemented, you should be able to add this to your settings to auto-format Jupyter notebooks:

"emeraldwalk.runonsave": {
  "commands": [
    {
      "match": "\.ipynb$",
      "cmd": "black ${file}"
    }
  ]
}
Answered By: Salvatore

A simple enough solution is to set the format notebook option to the same keybinding as save, as you suggested. Here’s how you can do that with VSCode Tasks:

tasks.json (in Command Palette "Tasks: Open User Tasks"):

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "cmd:save",
            "command": "${command:workbench.action.files.save}"
        },
        {
            "label": "cmd:format-notebook",
            "command": "${command:notebook.format}"
        },
        {
            "label": "cmd:format-notebook+save",
            "dependsOrder": "sequence",
            "dependsOn": [
                "cmd:format-notebook",
                "cmd:save"
            ]
        }
    ]
}

keybindings.json (in Command Palette "Preferences: Open Keyboard Shortcuts (JSON)"):

[
    {
        "key": "ctrl+s",
        "command": "workbench.action.tasks.runTask",
        "args": "cmd:format-notebook+save"
    }
]
Answered By: wossname