在版本控制下使用IPython笔记本


569

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

笔记本格式非常适合版本控制:如果要对笔记本及其输出进行版本控制,则效果很好。当人们只希望对输入进行版本控制时,就会感到烦恼,不包括可能是大型二进制Blob(尤其是电影和情节)的像元输出(又称“生成产品”)。特别是,我试图找到一个好的工作流程:

  • 让我可以选择是包含还是排除输出,
  • 防止我不想要我的输出,
  • 允许我将输出保持在本地版本中,
  • 允许我使用版本控制系统查看何时更改了输入(即,如果仅对版本进行控制,但是本地文件具有输出,那么我希望能够查看输入是否已更改(需要提交) )。由于本地文件具有输出,因此使用version control status命令将始终记录差异。)
  • 允许我从更新的干净笔记本中更新我的工作笔记本(包含输出)。(更新)

如前所述,如果我选择包括输出(例如,在使用nbviewer时是理想的),那么一切都很好。问题是,当我想要的版本控制输出。有一些工具和脚本可用于剥离笔记本的输出,但是我经常遇到以下问题:

  1. 我不小心用输出提交了一个版本,从而污染了我的存储库。
  2. 我清除了输出以使用版本控制,但实际上宁愿将输出保留在我的本地副本中(例如,有时需要一段时间才能重现)。
  3. Cell/All Output/Clear菜单选项相比,某些剥离输出的脚本会稍微改变格式,从而在差异中产生不必要的噪音。这可以通过一些答案解决。
  4. 将更改拉到文件的干净版本时,我需要找到某种方式将这些更改合并到我的工作笔记本中,而不必重新运行所有内容。 (更新)

我考虑了以下将要讨论的几种选择,但是还没有找到一个好的综合解决方案。完整的解决方案可能需要对IPython进行一些更改,或者可能依赖于一些简单的外部脚本。我目前使用mercurial,但是想要一个也可以与git一起使用的解决方案:理想的解决方案是版本控制无关的。

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

更新:我一直在使用修改过的笔记本版本,该.clean版本可以使用Gregory Crosswhite的建议每次保存时都保存一个版本。这满足了我的大部分约束,但以下问题尚未解决:

  1. 这还不是标准解决方案(需要对ipython源进行修改。是否可以通过简单的扩展来实现此行为?需要某种保存上的钩子。
  2. 我当前的工作流程存在一个问题,就是要进行更改。这些将进入.clean文件,然后需要以某种方式集成到我的工作版本中。(当然,我总是可以重新执行笔记本,但是这可能会很痛苦,尤其是如果某些结果取决于长时间的计算,并行计算等时。)关于如何解决这个问题我还没有个好主意。也许涉及像ipycache这样的扩展程序的工作流程可能会起作用,但这似乎有点太复杂了。

笔记

移除(剥离)输出

  • 笔记本计算机运行时,可以使用Cell/All Output/Clear菜单选项删除输出。
  • 有一些脚本可以删除输出,例如脚本nbstripout.py可以删除输出,但不会产生与使用笔记本界面相同的输出。最终将其包含在ipython / nbconvert存储库中,但已关闭,说明更改已包含在ipython / ipython中,但似乎尚未包含相应的功能。 (更新)话虽如此,Gregory Crosswhite的解决方案表明,即使不调用ipython / nbconvert,此操作也非常容易,因此,如果可以正确地挂接,则该方法可能是可行的。(但是,将其附加到每个版本控制系统似乎不是一个好主意-应该以某种方式挂接到笔记本机制上。)

新闻组

问题

拉取请求


github.com/ipython/ipython上作为问题添加或提交请求请求可以帮助您进一步实现这一目标,听起来是一件很棒的事情。
凯尔·凯利

4
一旦有了用于删除输出的工作脚本,就可以在提交之前使用Git“干净”过滤器自动应用它(请参阅清理/涂抹过滤器)。
Matthias 2013年

1
@foobarbecue该问题包含不令人满意的解决方法:每个解决方法都有至少一个限制。既然PR 4175已被合并,则可能可以制定一个完整的解决方案,但这仍然需要完成。如果有其他人在此期间没有提供令人满意的解决方案,我会尽快解决(作为答案)。
mforbes

1
@saroele我尚未找到推荐的解决方案:我打算使用该--script选项,但是该选项已被删除。我一直等到实现了保存后的钩子(已计划),在这一点上,我认为我将能够结合几种技术提供可接受的解决方案。
mforbes 2014年

1
@mforbes看来,您的评论在几天后才合并到PR。您或比我更有知识的人可以在这里发布答案,以显示如何使用新功能吗?
神户约翰·约翰逊2014年

Answers:


124

这是我的git解决方案。它允许您像往常一样添加和提交(和diff):这些操作不会改变您的工作树,并且同时(重新)运行笔记本不会改变您的git历史记录。

尽管这可能适用于其他VCS,但我知道它不能满足您的要求(至少VSC不可知)。尽管如此,它对我来说仍然是完美的,尽管没有什么特别出色的,而且很多人可能已经在使用它,但是我没有找到关于如何通过谷歌搜索来实现它的明确说明。因此对其他人可能有用。

  1. 将具有此内容的文件保存在某处(下面,让我们假设~/bin/ipynb_output_filter.py
  2. 使其可执行(chmod +x ~/bin/ipynb_output_filter.py
  3. 创建文件~/.gitattributes,内容如下

    *.ipynb    filter=dropoutput_ipynb
    
  4. 运行以下命令:

    git config --global core.attributesfile ~/.gitattributes
    git config --global filter.dropoutput_ipynb.clean ~/bin/ipynb_output_filter.py
    git config --global filter.dropoutput_ipynb.smudge cat
    

做完了!

局限性:

  • 它仅适用于git
  • 在git中,如果您在分支中somebranch并且执行了操作git checkout otherbranch; git checkout somebranch,则通常希望工作树保持不变。取而代之的是,您将丢失其来源在两个分支之间不同的笔记本的输出和单元编号。
  • 更一般而言,输出与Gregory的解决方案完全没有版本控制。为了不仅在每次执行涉及结帐的操作时都将其丢弃,可以通过将其存储在单独的文件中来更改方法(但请注意,在运行上述代码时,不知道提交ID!),并可能对其进行版本控制(但请注意,这将需要比a还要更多的东西git commit notebook_file.ipynb,尽管它至少可以避免git diff notebook_file.ipynbbase64垃圾)。
  • 也就是说,如果您确实拉出了包含某些输出的代码(即由不使用此方法的其他人提交的代码),则该输出将被正常检出。只有本地生产的输出会丢失。

我的解决方案反映了一个事实,即我个人不希望对生成的内容进行版本控制-请注意,进行包含输出的合并几乎可以保证使输出您的生产率两者无效。

编辑:

  • 如果你采用的解决方案,我认为它-那就是,全球-你会遇到麻烦的情况下,对于一些混帐回购协议,你到版本输出。因此,如果您要禁用特定git存储库的输出过滤,只需在其中创建一个文件.git / info / attributes,使用

    **。ipynb过滤器=

作为内容。显然,以同样的方式可以做相反的事情:仅对特定存储库启用过滤。

  • 该代码现在保留在自己的git repo中

  • 如果以上说明导致ImportErrors,请尝试在脚本路径之前添加“ ipython”:

    git config --global filter.dropoutput_ipynb.clean ipython ~/bin/ipynb_output_filter.py
    

编辑:2016年5月(2017年2月更新):我的脚本有几种选择-为了完整性,这是我所知道的列表:nbstripout其他 变体),nbstripjq


2
您如何处理合并您所做的更改的问题?您是否只需要重新生成所有输出?(我认为这是您第二个限制的体现。)
mforbes 2014年

1
@zhermes:此扩展版本应该可以
Pietro Battiston

1
有没有办法使用此git筛选器方法与外部diff工具一起使用?如果我使用普通的命令行工具,则应用该过滤器,但如果我将Meld用作差异工具,则不应用该过滤器。stackoverflow.com/q/30329615/578770
FA

1
为了避免让ImportError我改变上述内容以使用ipython运行:git config --global filter.dropoutput_ipynb.clean ipython ~/bin/ipynb_output_filter.py
chris838 2015年

1
令人敬畏的解决方案Pietro,谢谢:)在我的情况下,使用脚本时我做了两件事:1)我更喜欢在仓库的根目录中声明.gitattributes中的过滤器,而不是~/.gitattributes其他人具有与我相同的过滤器2 )我将regexp定义为workdir/**/*.ipynb filter=dropoutput_ipynb,并且如果我仍想将带有输出的笔记本推入并享受github中可书签显示的渲染,则将大多数笔记本放在workdir / =>中,我只是将其放在该文件夹之外。
斯文德(Svend)2015年

63

我们有一个合作项目,产品为Jupyter Notebooks,并且在过去的六个月中一直使用一种非常有效的方法:我们.py自动激活保存文件并跟踪.ipynb文件和.py文件。

这样,如果有人想要查看/下载最新的笔记本,则可以通过github或nbviewer进行操作,如果有人想要查看笔记本代码的更改方式,则只需查看.py文件的更改即可。

对于Jupyter笔记本服务器,可以通过添加以下行来完成

import os
from subprocess import check_call

def post_save(model, os_path, contents_manager):
    """post-save hook for converting notebooks to .py scripts"""
    if model['type'] != 'notebook':
        return # only do this for notebooks
    d, fname = os.path.split(os_path)
    check_call(['jupyter', 'nbconvert', '--to', 'script', fname], cwd=d)

c.FileContentsManager.post_save_hook = post_save

jupyter_notebook_config.py文件,然后重新启动笔记本服务器。

如果不确定在哪个目录中找到jupyter_notebook_config.py文件,则可以键入jupyter --config-dir,如果在该目录中找不到文件,则可以通过键入创建文件jupyter notebook --generate-config

对于Ipython 3笔记本服务器,可以通过添加以下行来完成

import os
from subprocess import check_call

def post_save(model, os_path, contents_manager):
    """post-save hook for converting notebooks to .py scripts"""
    if model['type'] != 'notebook':
        return # only do this for notebooks
    d, fname = os.path.split(os_path)
    check_call(['ipython', 'nbconvert', '--to', 'script', fname], cwd=d)

c.FileContentsManager.post_save_hook = post_save

ipython_notebook_config.py文件,然后重新启动笔记本服务器。这些行来自github问题答案@minrk提供,@ dror也将它们包括在他的SO答案中。

对于Ipython 2笔记本服务器,这可以通过使用以下方法启动服务器来完成:

ipython notebook --script

或通过添加行

c.FileNotebookManager.save_script = True

ipython_notebook_config.py文件,然后重新启动笔记本服务器。

如果不确定在哪个目录中找到ipython_notebook_config.py文件,则可以键入ipython locate profile default,如果在该目录中找不到文件,则可以通过键入创建文件ipython profile create

这是我们在github上使用此方法的项目:这是探索笔记本最近更改github示例

我们对此感到非常高兴。


1
感谢您提供额外的证据,证明使用--script实际上可以奏效。问题是如果保留图像,实际的笔记本可能很大。这种方法的理想解决方案可能是使用git-annex之类的方法来仅跟踪最新的完整笔记本。
mforbes 2014年

在Ipython 3.x中--script已弃用。ipython.org/ipython-doc/3/whatsnew/version3.html
Dror

感谢@dror,我已经更新了我的答案,以提供minrk的ipython 3.x解决方案,正如您在此处提供的那样。
Rich Signell

10
更新:由于iPython的Jupyter的“大分裂”,该解决方案在iPython版本4中被打破。要将此解决方案调整为版本4,请使用命令jupyter notebook --generate-config创建配置文件。该命令jupyter --config-dir找出哪个目录包含配置文件。@Rich给出的代码段应添加到名为的文件中jupyter_notebook_config.py。其余的都像以前一样工作。
mobius饺子2015年

2
除了由@mobiusdumpling点,替换check_call(['ipython'check_call(['jupyter',否则你会得到一个警告ipython nbconvert已被废弃,你应该使用jupyter nbconvert来代替。(Jupyter v4.1.0,iPython v4.1.2)
cutculus

36

nbstripout基于MinRK的gist创建了一个,它同时支持Git和Mercurial(感谢mforbes)。它既可以在命令行上单独使用,也可以用作过滤器,可以通过nbstripout install/ 轻松地(取消)安装在当前存储库中nbstripout uninstall

PyPI或简单地获取

pip install nbstripout

我正在考虑一个工作流,在该工作流中,我将同时使用上述保存后挂钩自动创建.ipynb和相应的.py。我想对差异使用.py-nbstripout能够从单元执行计数器中清除.py文件(#In [1]更改为In [*]),以便它们不会使差异变得混乱,或者我应该创建一个简单的脚本来做到这一点?
KrzysztofSłowiński17年

1
@KrzysztofSłowiński不,nbstripout因为它依赖于Notebook的JSON格式,所以不容易支持此用例。您最好编写专门针对用例的脚本。
kynan


13

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

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

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

让我可以选择是包含还是排除输出,

.md/.py/.R文件仅包含输入单元格。您应该始终跟踪该文件。.ipynb仅在要跟踪输出时才对文件进行版本控制。

防止我不想要我的输出,

添加*.ipynb.gitignore

允许我将输出保持在本地版本中,

输出保留在(本地).ipynb文件中

允许我使用版本控制系统查看何时更改了输入(即,如果仅对版本进行控制,但是本地文件具有输出,那么我希望能够查看输入是否已更改(需要提交) )。由于本地文件具有输出,因此使用version control status命令将始终记录差异。)

.py/.R.md文件上的差异是您要查找的

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

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

我对Jupytext的喜爱是,可以在您最喜欢的IDE中编辑笔记本(以.py/.R.md文件的形式 )。使用这种方法,重构笔记本变得容易。完成后,您只需要在Jupyter中刷新笔记本即可。

如果想尝试一下:用安装Jupytext,pip install jupytext然后重新启动Jupyter Notebook或Lab编辑器。打开要版本控制的笔记本,然后使用Jupyter笔记本中的Jupytext菜单(或Jupyter Lab中的Jupytext命令)将与Markdown文件(或脚本)配对。保存您的笔记本,您将获得两个文件:原始,以及笔记本的承诺文本表示形式,非常适合版本控制!.ipynb

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


13

更新:现在您可以 直接在Visual Studio Code中编辑Jupyter Notebook文件。您可以选择编辑笔记本或转换后的python文件。

我终于找到了一种有效且简单的方法来使Jupyter和Git完美地玩耍。我仍处于起步阶段,但我已经认为它比所有其他复杂解决方案要好得多。

Visual Studio Code是Microsoft提供的一个很酷的开源代码编辑器。它具有出色的Python扩展,现在允许您将Jupyter Notebook作为python代码导入。现在,您还可以直接编辑Jupyter Notebooks

将笔记本导入到python文件后,所有代码和markdown都将合并在一个普通的python文件中,并在注释中带有特殊标记。您可以在下图中看到:

带有笔记本的VSCode编辑器转换为python

您的python文件仅包含笔记本输入单元格的内容。输出将在拆分窗口中生成。您的笔记本中有纯代码,仅在执行时它不会更改。没有与您的代码混合输出。没有奇怪的JSON难以理解的格式来分析差异。

只是纯python代码,您可以在其中轻松识别每个差异。

我什至无需再对.ipynb文件进行版本控制。我可以打*.ipynb线.gitignore

需要生成一个笔记本以与他人发布或共享吗?没问题,只需在交互式python窗口中单击导出按钮

将python文件导出为Notebook格式

如果您直接编辑笔记本,则现在有一个图标Convert and save to a python scriptVisual Studio Code中的Jupyter图标

这是Visual Studio Code中笔记本的屏幕截图:

在VSCode中编辑笔记本

我已经使用了一天,但最终我可以将Jupyter与Git一起使用。

PS:VSCode代码完成比Jupyter好很多。


12

(2017-02)

策略

  • on_commit():
    • 剥离输出> name.ipynb(nbstripout,)
    • 剥离输出> name.clean.ipynb(nbstripout,)
    • 始终nbconvert为python:name.ipynb.py(nbconvert
    • 始终转换为markdown:name.ipynb.md(nbconvertipymd
  • vcs.configure():
    • git difftool,mergetool:来自nbdime的nbdiff和nbmerge

工具


11

与2019年更好的方法相比,上述2016年非常受欢迎的答案是不一致的黑客。

存在几种选择,回答该问题的最佳选择是Jupytext。

文字

在Jupytext迈向数据科学文章

它与版本控制一起工作的方式是将.py和.ipynb文件都放入版本控制中。如果需要输入差异,请查看.py;如果需要最新的渲染输出,请查看.ipynb。

值得注意的是:VS Studio,nbconvert,nbdime,氢

我认为,通过更多的工作,VS工作室和/或氢气(或类似产品)将成为该工作流程解决方案中的主导者。


9

只是遇到“ jupytext”,它看起来是一个完美的解决方案。它从笔记本生成一个.py文件,然后使两者保持同步。您可以通过.py文件对输入进行版本控制,比较和合并,而不会丢失输出。当您打开笔记本时,它使用.py作为输入单元格,并使用.ipynb作为输出单元格。如果要在git中包含输出,则只需添加ipynb。

https://github.com/mwouts/jupytext


9

由于存在许多处理笔记本版本控制的策略和工具,因此我尝试创建流程图以选择合适的策略(于2019年4月创建)

选择版本控制策略的决策流程


8

如所指出,在--script中已弃用3.x。可以通过应用后保存挂钩来使用此方法。特别要添加以下内容ipython_notebook_config.py

import os
from subprocess import check_call

def post_save(model, os_path, contents_manager):
    """post-save hook for converting notebooks to .py scripts"""
    if model['type'] != 'notebook':
        return # only do this for notebooks
    d, fname = os.path.split(os_path)
    check_call(['ipython', 'nbconvert', '--to', 'script', fname], cwd=d)

c.FileContentsManager.post_save_hook = post_save

该代码取自#8009


感谢您演示保存后挂钩的用法。不幸的是,如前所述,从.py文件返回笔记本是有问题的,因此,不幸的是,这不是一个完整的解决方案。(我善意的期望它,因为它是非常好的,DIFF .py文件,而不是笔记本电脑也许是新的。笔记本DIFF功能将非常有用。
mforbes

1
谢谢!现在--script,无论版本控制如何,我都在使用此技巧重现该行为。起初我遇到了一些问题,以防万一我可以节省一些时间:1)如果ipython_notebook_config.py配置文件文件夹中缺少,请运行ipython profile create以生成它。2)如果似乎后保存挂钩被忽略,请运行ipython with --debug诊断问题。3)如果脚本失败,错误ImportError: No module named mistune-简单的安装minstue: pip install mistune

7

不幸的是,我对Mercurial的了解不多,但是我可以为您提供一个与Git一起使用的可行解决方案,希望您能够将我的Git命令转换为与Mercurial等效的命令。

对于后台,在Git中,该add命令将对文件所做的更改存储到暂存区中。完成此操作后,Git会忽略对该文件的任何后续更改,除非您还告诉它也要暂存它们。因此,以下脚本(对于每个给定的文件)会剥离所有outputsprompt_number sections,分段处理剥离的文件,然后还原原始文件:

注意:如果运行此命令会收到类似的错误消息ImportError: No module named IPython.nbformat,请使用ipython而不是运行脚本python

from IPython.nbformat import current
import io
from os import remove, rename
from shutil import copyfile
from subprocess import Popen
from sys import argv

for filename in argv[1:]:
    # Backup the current file
    backup_filename = filename + ".backup"
    copyfile(filename,backup_filename)

    try:
        # Read in the notebook
        with io.open(filename,'r',encoding='utf-8') as f:
            notebook = current.reads(f.read(),format="ipynb")

        # Strip out all of the output and prompt_number sections
        for worksheet in notebook["worksheets"]:
            for cell in worksheet["cells"]:
               cell.outputs = []
               if "prompt_number" in cell:
                    del cell["prompt_number"]

        # Write the stripped file
        with io.open(filename, 'w', encoding='utf-8') as f:
            current.write(notebook,f,format='ipynb')

        # Run git add to stage the non-output changes
        print("git add",filename)
        Popen(["git","add",filename]).wait()

    finally:
        # Restore the original file;  remove is needed in case
        # we are running in windows.
        remove(filename)
        rename(backup_filename,filename)

在要提交更改的文件上运行脚本后,只需运行git commit


谢谢你的建议。Mercurial确实没有像git这样的临时区域(尽管可以为此目的使用Mercurial队列)。同时,我尝试将此代码添加到保存钩子中,以保存带有.clean扩展名的纯净版本。不幸的是,如果不直接修改IPython,我将看不到如何做到这一点(尽管这一变化是微不足道的)。我会玩一会儿,看看它是否适合我的所有需求。
mforbes

6

我使用非常务实的方法。适用于多个笔记本的多个侧面。而且它甚至使我能够“转移”笔记本。它既适用于Windows,也适用于Unix / MacOS。
Al认为很简单,就是解决上面的问题...

概念

基本上,跟踪.ipnyb-file,仅跟踪相应的.py-file。
通过使用该选项启动笔记本服务器--script保存笔记本时将自动创建/保存该文件。

这些.py-files确实包含所有输入;非代码和单元格边框一起保存到注释中。可以将这些文件读取/导入(并拖动)到笔记本服务器中,以(重新)创建笔记本。只有输出消失了;直到重新运行。

我个人使用mercurial.py文件进行版本跟踪。并使用常规(命令行)命令进行添加,签入(添加)。大多数其他(D)VCS都允许这样做。

现在很容易跟踪历史;在.py小,文本和简单的差异。有时,我们需要一个克隆(只是分支;在那里启动一个第二个笔记本),或者一个旧版本(签出并导入到笔记本服务器中),等等。

提示与技巧

  • * .ipynb添加到' .hgignore ',这样Mercurial知道它可以忽略那些文件
  • 创建一个(bash)脚本来启动服务器(使用该--script选项)并对其进行版本跟踪
  • 保存笔记本不会保存.py-file,但不会将其检入。
    • 这是一个缺点:人们可能会忘记
    • 它也是一个功能:可以保存笔记本(并在以后继续)而无需对存储库历史记录进行聚类。

祝愿

  • 在笔记本仪表板中具有用于签到/添加/等的按钮会很好
  • (例如)签出file@date+rev.py应该会很有帮助。也许我会这样做一次。到目前为止,我只是手工完成。

您如何从.py文件回到笔记本?我喜欢这种方法,但是因为.ipynb-> .py-> .ipynb可能有损,所以我没有认真考虑这一点。
mforbes

这很容易:加载它,例如,将其放在de Notebook-dashboard上。除了“输出数据”之外,什么都没有丢失
艾伯特(Albert)

如果这是真的,那么我认为这接近想法,但是我似乎记得,IPython没有承诺在从.py.ipynb格式的过渡中完全保留数据。有一个问题 –也许这将构成完整解决方案的基础。
mforbes 2014年

我在从.py文件转换到文件时遇到一些困难.ipynbnbconvert似乎还不支持此功能,并且由于我是ipython notebook手动运行的,所以我没有笔记本仪表板。您对如何实现这种向后转换有任何一般性建议吗?
mforbes 2014年

当然,从.py笔记本到笔记本的转换不是为了往返。因此,尽管它很适合您,但这并不是真正的通用解决方案。
holdenweb

3

如果出现如下所示的Unicode解析错误,请按照Pietro Battiston的出色脚本进行跟进:

Traceback (most recent call last):
  File "/Users/kwisatz/bin/ipynb_output_filter.py", line 33, in <module>
write(json_in, sys.stdout, NO_CONVERT)
  File "/Users/kwisatz/anaconda/lib/python2.7/site-packages/IPython/nbformat/__init__.py", line 161, in write
fp.write(s)
UnicodeEncodeError: 'ascii' codec can't encode character u'\u2014' in position 11549: ordinal not in range(128)

您可以在脚本的开头添加:

reload(sys)
sys.setdefaultencoding('utf8')

3

我已经建立了可以解决这个问题的python包

https://github.com/brookisme/gitnb

它提供了具有git启发式语法的CLI,以在git存储库中跟踪/更新/ diff笔记本。

这是一个例子

# add a notebook to be tracked
gitnb add SomeNotebook.ipynb

# check the changes before commiting
gitnb diff SomeNotebook.ipynb

# commit your changes (to your git repo)
gitnb commit -am "I fixed a bug"

请注意,我使用“ gitnb commit”的最后一步是提交到您的git repo。它本质上是一个包装

# get the latest changes from your python notebooks
gitnb update

# commit your changes ** this time with the native git commit **
git commit -am "I fixed a bug"

还有其他几种方法,可以对其进行配置,以便在每个阶段都需要更多或更少的用户输入,但这就是一般的想法。


3

深入研究之后,我终于在Jupyter docs上找到了这个相对简单的预保存钩子。它将剥离单元输出数据。您必须将其粘贴到jupyter_notebook_config.py文件中(有关说明,请参见下文)。

def scrub_output_pre_save(model, **kwargs):
    """scrub output before saving notebooks"""
    # only run on notebooks
    if model['type'] != 'notebook':
        return
    # only run on nbformat v4
    if model['content']['nbformat'] != 4:
        return

    for cell in model['content']['cells']:
        if cell['cell_type'] != 'code':
            continue
        cell['outputs'] = []
        cell['execution_count'] = None
        # Added by binaryfunt:
        if 'collapsed' in cell['metadata']:
            cell['metadata'].pop('collapsed', 0)

c.FileContentsManager.pre_save_hook = scrub_output_pre_save

Rich Signell的答案中

如果不确定在哪个目录中找到jupyter_notebook_config.py文件,则可以键入jupyter --config-dir[进入命令提示符/终端],如果找不到该文件,则可以通过键入创建文件jupyter notebook --generate-config


1
我会注意到,该解决方案永远不会将任何输出保存到磁盘,并且在某种程度上与版本控制问题无关。
bdforbes

2

我做了Albert&Rich所做的事情-不要对.ipynb文件进行版本控制(因为这些文件可能包含图像,会变得凌乱)。而是始终运行ipython notebook --script或放置c.FileNotebookManager.save_script = True配置文件中,以便.py在保存笔记本时始终创建(可版本化)文件。

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

现在,签出一个回购协议后,只需运行python py_file_to_notebooks.py即可生成ipynb文件。切换分支后,您可能必须运行python py_file_to_notebooks.py -ov以覆盖现有的ipynb文件。

为了安全起见,最好也添加 *.ipynb到您的.gitignore文件中。

编辑:我不再这样做了,因为(A)每次签出分支时都必须从py文件重新生成笔记本,并且(B)丢失笔记本中的其他东西,例如减价。我改为使用git过滤器从笔记本中剥离输出。有关如何执行此操作的讨论在这里


我喜欢这个主意,但是经过测试,发现从.py文件到文件的转换.ipynb是有问题的,尤其是对于还没有转换器的版本4笔记本而言。当前需要使用v3导入程序,然后转换为v4,我对此复杂的过程有点担心。另外,.py如果笔记本主要是Julia代码,则文件不是一个很好的选择!最后,--script它已被弃用,所以我认为挂钩是可行的方法。
mforbes

链接中的git过滤器解决方案很好,您应该从此处复制答案:-)
mcarans 2015年

2

好的,因此,按照此处的讨论,当前最好的解决方案是使git过滤器在提交时自动剥离ipynb文件的输出。

这是我为使其正常工作所做的事情(摘自该讨论内容):

当您无法导入最新的IPython 时,我稍微修改了cfriedline的nbstripout文件,以提供一个提示错误:https : //github.com/petered/plato/blob/fb2f4e252f50c79768920d0e47b870a8d799e92b/notebooks/config/strip_notebook_output并将其添加到我的仓库中,说出来./relative/path/to/strip_notebook_output

还将文件.gitattributes文件添加到仓库的根目录,其中包含:

*.ipynb filter=stripoutput

并创建了一个setup_git_filters.sh包含

git config filter.stripoutput.clean "$(git rev-parse --show-toplevel)/relative/path/to/strip_notebook_output" 
git config filter.stripoutput.smudge cat
git config filter.stripoutput.required true

然后跑了source setup_git_filters.sh。$(git rev-parse ...)是在任何(Unix)机器上找到仓库的本地路径。


1

此jupyter扩展使用户可以将jupyter笔记本直接推送到github。

请看这里

https://github.com/sat28/githubcommit


你能解释一下这是什么吗?这种矛盾不是特别清楚。
Alex Monras

@AlexMonras这将直接在jupyter笔记本中添加一个按钮,您可以在其中通过提交消息将笔记本推送到GitHub存储库中
坐在

1

这是2020年4月,有很多用于Jupyter笔记本版本控制的策略和工具。这是您可以使用的所有工具的简要概述,

  • nbdime-非常适合笔记本的本地差异化和合并

  • nbstripout-一个git过滤器,可在每次提交前自动删除笔记本的输出

  • jupytext-将.py随播文件同步到每个笔记本。您只提交.py文件

  • nbconvert-将笔记本转换为python脚本或HTML(或两者)并提交这些备用文件类型

  • ReviewNB-显示笔记本diff(以及输出),以查看GitHub上的任何提交或请求请求。人们还可以在笔记本电脑的单元格上写评论以讨论更改(以下屏幕截图)。

在此处输入图片说明

免责声明:我构建了ReviewNB。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.