将IPython笔记本保持在版本控制下的好策略是什么?

笔记本格式非常适合版本控制:如果想对笔记本和输出进行版本控制,那么这种方法非常有效。当人们只想对输入进行版本控制,而不包括单元格输出时,就会出现烦恼。“构建产品”),可以是大的二进制blob,特别是电影和情节。特别是,我试图找到一个好的工作流程:

allows me to choose between including or excluding output, prevents me from accidentally committing output if I do not want it, allows me to keep output in my local version, allows me to see when I have changes in the inputs using my version control system (i.e. if I only version control the inputs but my local file has outputs, then I would like to be able to see if the inputs have changed (requiring a commit). Using the version control status command will always register a difference since the local file has outputs.) allows me to update my working notebook (which contains the output) from an updated clean notebook. (update)

如前所述,如果我选择包含输出(例如,在使用nbviewer时,这是可取的),那么一切都没问题。问题是当我不想对输出进行版本控制时。有一些工具和脚本可以剥离笔记本的输出,但我经常遇到以下问题:

I accidentally commit a version with the the output, thereby polluting my repository. I clear output to use version control, but would really rather keep the output in my local copy (sometimes it takes a while to reproduce for example). Some of the scripts that strip output change the format slightly compared to the Cell/All Output/Clear menu option, thereby creating unwanted noise in the diffs. This is resolved by some of the answers. When pulling changes to a clean version of the file, I need to find some way of incorporating those changes in my working notebook without having to rerun everything. (update)

我已经考虑了下面将要讨论的几个选项,但是还没有找到一个好的全面的解决方案。完整的解决方案可能需要对IPython进行一些更改,或者可能依赖于一些简单的外部脚本。我目前使用mercurial,但希望有一个解决方案也能与git一起工作:一个理想的解决方案是版本控制不可知的。

这个问题已经讨论过很多次了,但是从用户的角度来看,还没有明确的解决方案。这个问题的答案应该能提供明确的策略。如果它需要IPython的最新(甚至是开发版)版本或易于安装的扩展,那是没问题的。

更新:我一直在玩我修改过的笔记本版本,它可以选择保存一个.clean版本,每次保存都使用Gregory Crosswhite的建议。这满足了我的大部分约束条件,但留下了以下问题:

This is not yet a standard solution (requires a modification of the ipython source. Is there a way of achieving this behaviour with a simple extension? Needs some sort of on-save hook. A problem I have with the current workflow is pulling changes. These will come in to the .clean file, and then need to be integrated somehow into my working version. (Of course, I can always re-execute the notebook, but this can be a pain, especially if some of the results depend on long calculations, parallel computations, etc.) I do not have a good idea about how to resolve this yet. Perhaps a workflow involving an extension like ipycache might work, but that seems a little too complicated.

笔记

移除(剥离)输出

When the notebook is running, one can use the Cell/All Output/Clear menu option for removing the output. There are some scripts for removing output, such as the script nbstripout.py which remove the output, but does not produce the same output as using the notebook interface. This was eventually included in the ipython/nbconvert repo, but this has been closed stating that the changes are now included in ipython/ipython,but the corresponding functionality seems not to have been included yet. (update) That being said, Gregory Crosswhite's solution shows that this is pretty easy to do, even without invoking ipython/nbconvert, so this approach is probably workable if it can be properly hooked in. (Attaching it to each version control system, however, does not seem like a good idea — this should somehow hook in to the notebook mechanism.)

新闻组

关于版本控制的笔记本格式的思考。

问题

977:笔记本功能请求(打开)。 1280:清除-all保存选项(打开)。(从下面的讨论。) 3295:自动导出的笔记本:只导出显式标记的单元格(关闭)。扩展解决11添加写和执行魔法(合并)。

把请求

1621: clear In[] prompt numbers on "Clear All Output" (Merged). (See also 2519 (Merged).) 1563: clear_output improvements (Merged). 3065: diff-ability of notebooks (Closed). 3291: Add the option to skip output cells when saving. (Closed). This seems extremely relevant, however was closed with the suggestion to use a "clean/smudge" filter. A relevant question what can you use if you want to strip off output before running git diff? seems not to have been answered. 3312: WIP: Notebook save hooks (Closed). 3747: ipynb -> ipynb transformer (Closed). This is rebased in 4175. 4175: nbconvert: Jinjaless exporter base (Merged). 142: Use STDIN in nbstripout if no input is given (Open).


当前回答

我做了Albert & Rich所做的——不要给.ipynb文件做版本(因为这些文件可能包含图像,这会变得混乱)。相反,要么总是运行ipython notebook——script,要么放c.FileNotebookManager。在你的配置文件中save_script = True,这样当你保存你的笔记本时,总是会创建一个(可版本的).py文件。

为了重新生成笔记本(在签出一个repo或切换一个分支之后),我将脚本py_file_to_notebook .py放在我存储笔记本的目录中。

现在,签出一个repo之后,只需运行python py_file_to_notebook .py来生成ipynb文件。切换分支后,您可能需要运行python py_file_to_notebook .py -ov来覆盖现有的ipynb文件。

为了安全起见,也可以加上 *。Ipynb到你的。gitignore文件。

编辑:我不再这样做了,因为(A)每次签出分支时,你都必须从py文件中重新生成你的笔记本,(B)在笔记本中有其他东西,如markdown,你会丢失。相反,我使用git过滤器从笔记本中剥离输出。关于如何做到这一点的讨论在这里。

其他回答

你可以使用这个jupyter扩展。它可以让你直接上传你的ipython笔记本到github。

https://github.com/sat28/githubcommit

我还制作了一个视频来演示这些步骤 youtube链接

现在是2020年4月,Jupyter笔记本版本控制有很多策略和工具。这里是你可以使用的所有工具的快速概述,

nbdime - Nice for local diff'ing and merging of notebooks nbstripout - A git filter to automatically remove notebook outputs before each commit jupytext - Keeps a .py companion file sync'ed to each notebook. You only commit .py files nbconvert - Convert notebooks to a python script or HTML (or both) and commit these alternate file types ReviewNB - Shows notebook diff (along with output) for any commit or pull request on GitHub. One can also write comments on notebook cells to discuss changes (screenshot below).

免责声明:我创建了ReviewNB。

下面文章中讨论的想法如何,笔记本的输出应该保存在哪里,理由是生成它可能需要很长时间,而且它很方便,因为GitHub现在可以渲染笔记本。添加了用于导出.py文件的自动保存钩子,用于diffs和.html,以便与不使用笔记本或git的团队成员共享。

https://towardsdatascience.com/version-control-for-jupyter-notebook-3e6cef13392d

下面是Cyrille rosant为IPython 3.0提供的一个新解决方案,它坚持标记文件,而不是基于json的ipymd文件:

https://github.com/rossant/ipymd

在删除笔记本的输出数年之后,我试图提出一个更好的解决方案。我现在使用Jupytext,这是我设计的Jupyter Notebook和Jupyter Lab的扩展。

Jupytext可以转换Jupyter笔记本到各种文本格式(脚本,Markdown和R Markdown)。反之。它还提供了将笔记本与这些格式之一配对的选项,并自动同步笔记本的两种表示形式(.ipynb和.md/.py/)。R文件)。

让我来解释一下Jupytext是如何回答上述问题的:

允许我在包含或不包含输出之间进行选择,

。海事/ . py。R文件只包含输入单元格。您应该始终跟踪该文件。只有在希望跟踪输出时,才对.ipynb文件进行版本控制。

防止我不小心提交输出,如果我不想要它,

将 *.ipynb 添加到 .gitignore

允许我保持本地版本的输出,

输出保存在(local) .ipynb文件中

允许我看到当我使用我的版本控制系统在输入中有变化时(即,如果我只控制输入,但我的本地文件有输出,那么我希望能够看到输入是否发生了变化(需要提交)。使用版本控制状态命令将总是注册一个差异,因为本地文件有输出。)

.py/。R或。md文件是你要找的

允许我从更新的干净笔记本更新我的工作笔记本(其中包含输出)。(更新)

获取.py/. xml文件的最新修订版本。R或。md文件,并刷新你的笔记本在Jupyter (Ctrl+R)。您将从文本文件中获得最新的输入单元格,并从.ipynb文件中获得匹配的输出。内核不受影响,这意味着您的局部变量被保留-您可以继续在离开它的地方工作。

我喜欢Jupytext的地方是它的笔记本(以.py/。R或.md文件)可以在您喜欢的IDE中编辑。使用这种方法,重构笔记本变得很容易。一旦你完成了,你只需要在Jupyter刷新笔记本。

如果你想尝试一下:安装Jupytext与pip安装Jupytext并重新启动你的Jupyter笔记本或实验室编辑器。打开要进行版本控制的笔记本,并使用Jupyter notebook中的Jupytext菜单(或Jupyter Lab中的Jupytext命令)将其配对到Markdown文件(或脚本)。保存您的笔记本,您将得到两个文件:原始的.ipynb,加上承诺的笔记本文本表示,这非常适合版本控制!

对于那些可能感兴趣的人:在命令行上也可以使用Jupytext。