如何避免 Jupyter cell-id 始终发生变化,从而避免 VCS 差异?

lef*_*out 9 ipython jupyter-notebook

正如q/66678305中所讨论的,较新的 Jupyter 版本除了单元的源代码和输出之外还存储ID,用于链接到单元等目的。

\n

然而,这些 ID 并不稳定,即使单元的源代码未被触及,它们也会经常发生变化。因此,如果您使用.ipynbgit 等版本控制文件,则提交最终会出现许多听起来相当有趣的 \xe2\x80\x9cchanged 行\xe2\x80\x9d,这些行与所做的任何实际更改不对应在提交中。喜欢,

\n
   {\n "cell_type": "code",\n "execution_count": null,\n-   "id": "尊重的违规",\n+ "id": "事件获胜",\n "元数据": {},\n "输出": [],
\n

有办法防止这种情况吗?

\n

lef*_*out 2

Linux 上 Git 的答案。可能也适用于 MacOS,但不适用于 Windows。

最好不要对.ipynbJupyter 保存的文件进行 VCS,而是使用不包含所有易失性信息的过滤版本。为此,可以使用各种git hook ;我正在使用的基于https://github.com/toobaz/ipynb_output_filter/blob/master/ipynb_output_filter.py

奇怪的是,事实证明无法修改该脚本以"id"从单元格中删除该字段。也就是说,如果您尝试在过滤循环中删除该字段,例如

        for field in ("prompt_number", "execution_number", "id"):
            if field in cell:
                del cell[field]
Run Code Online (Sandbox Code Playgroud)

那么writefrom 的函数jupyter_nbformat只会放回一个id。可以仅将id更改为常量,但随后 Jupyter 会抱怨 id 不唯一。

作为规避这个问题的方法,我现在使用这个过滤器来简单地grep删除 ID:

#!/bin/bash
grep -v '^ *"id": "[a-z\-]*",$'
Run Code Online (Sandbox Code Playgroud)

将其存储在 例如 中~/bin/ipynb_output_filter.sh,使其可执行 ( chmod +x ~/bin/ipynb_output_filter.sh) 并确保您拥有以下~/.gitattributes文件:

*.ipynb filter=dropoutput_ipynb
Run Code Online (Sandbox Code Playgroud)

并在您的 git 配置(全局~/.gitconfig或项目)中

[core]
         attributesfile = ~/.gitattributes
[filter "dropoutput_ipynb"]
         clean = ~/bin/ipynb_output_filter.sh
         smudge = cat
Run Code Online (Sandbox Code Playgroud)

如果您还想使用标准的 python 过滤器,您可以在grepin之前调用它~/bin/ipynb_output_filter.sh,例如

#!/bin/bash
~/bin/ipynb_output_filter.py | grep -v '^ *"id": "[a-z\-]*",$'
Run Code Online (Sandbox Code Playgroud)