version-control - ipynb - jupyter notebook version control




Использование ноутбуков IPython под управлением версий (10)

Что такое хорошая стратегия для хранения ноутбуков IPython под контролем версий?

Формат ноутбука вполне подходит для управления версиями: если вы хотите контролировать версию ноутбука и выходы, то это работает очень хорошо. Досада возникает, когда вы хотите только управлять версией ввода, исключая выходы ячейки (например, «build products»), которые могут быть большими двоичными блоками, особенно для фильмов и сюжетов. В частности, я пытаюсь найти хороший рабочий процесс, который:

  • позволяет мне выбирать между включением или исключением выхода,
  • мешает мне случайно совершить вывод, если я этого не хочу,
  • позволяет мне вести вывод в моей локальной версии,
  • позволяет мне видеть, когда у меня есть изменения в входах с использованием моей системы управления версиями (т. е. если я только версия управляет входами, но у моего локального файла есть выходы, то я хотел бы видеть, изменились ли входы (требуется фиксация ). Использование команды управления версиями всегда будет регистрировать разницу, так как локальный файл имеет выходы.)
  • позволяет обновить мой рабочий ноутбук (который содержит выход) из обновленного чистого ноутбука. (Обновить)

Как уже упоминалось, если я решил включить выходы (что желательно при использовании 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 repo, но это было закрыто, заявив, что изменения теперь включены в ipython/ipython , но соответствующая функциональность, похоже, еще не была включена. (обновление). Говоря это, решение Gregory Crosswhite показывает, что это довольно легко сделать, даже не вызывая ipython/nbconvert , поэтому этот подход, вероятно, работоспособен, если он может быть правильно подключен. (Прикрепляя его к каждой системе управления версиями, однако , не кажется хорошей идеей - это должно как-то зацепиться за механизм ноутбука.)

Телеконференции

вопросы

Вытянуть запросы


(2017-02)

стратегии

  • on_commit ():
    • разделите вывод> name.ipynb ( nbstripout ,)
    • разделите вывод> name.clean.ipynb ( nbstripout ,)
    • всегда nbconvert в python: name.ipynb.py ( nbconvert )
    • всегда конвертировать в уценку: name.ipynb.md ( nbconvert , ipymd )
  • vcs.configure ():
    • git difftool, mergetool: nbdiff и nbmerge из nbdime

инструменты

  • nbstripout : nbstripout выходы из ноутбука
  • ipynb_output_filter : ipynb_output_filter выходы из ноутбука
  • ipymd : конвертировать между {Jupyter, Markdown, O'Reilly Atlas Markdown, OpenDocument, .py}
  • nbdime : «Инструменты для разметки и слияния ноутбуков Jupyter». (2015)
    • src: https://github.com/jupyter/nbdime
    • docs: http://nbdime.readthedocs.io/
      • nbdiff : сравнить ноутбуки в терминальном режиме
      • nbmerge : трехстороннее слияние ноутбуков с автоматическим разрешением конфликтов
        • nbdime nbmerge работает как инструмент объединения git
      • nbdiff-web : показывает вам богатый nbdiff-web ноутбуков
      • nbmerge-web : дает вам веб-инструмент для трехстороннего слияния для ноутбуков
      • nbshow : представить единственную записную книжку в терминальном режиме

Вот мое решение с git. Это позволяет вам просто добавлять и фиксировать (и различать), как обычно: эти операции не изменят ваше рабочее дерево, и в то же время (пере) запуск ноутбука не изменит вашу историю 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 git checkout otherbranch; git checkout somebranch , вы обычно ожидаете, что рабочее дерево останется неизменным. Здесь вместо этого вы потеряете выходную и ячеистую нумерацию ноутбуков, источник которых отличается между двумя ветвями.
  • в общем случае выход не является версией вообще, как в случае с решением Грегори. Чтобы не просто выбросить его каждый раз, когда вы делаете что-либо, связанное с проверкой, этот подход можно изменить, сохранив его в отдельных файлах (но обратите внимание, что во время выполнения вышеуказанного кода идентификатор фиксации неизвестен!), и, возможно, их версию (но обратите внимание, что для этого потребуется нечто большее, чем git commit notebook_file.ipynb , хотя, по крайней мере, он сохранит git diff notebook_file.ipynb без мусора base64).
  • что, кстати, если вы делаете код (т. е. совершенный кем-то другим, не использующим этот подход), который содержит некоторый результат, выход проверяется нормально. Утеряна только локально произведенная продукция.

Мое решение отражает тот факт, что мне лично не нравится держать сгенерированный материал версией - обратите внимание, что выполнение слияний с выходом почти гарантированно приводит к недействительности вывода или вашей производительности или того и другого.

РЕДАКТИРОВАТЬ:

  • если вы примете решение, как я предложил, то есть во всем мире - у вас возникнут проблемы в случае, если для какого-либо git-репо вы хотите вывести версию. Поэтому, если вы хотите отключить фильтрацию вывода для конкретного репозитория git, просто создайте в нем файл .git / info / attributes , с

    **. ipynb filter =

как содержание. Ясно, что таким же образом можно сделать обратное: включить фильтрацию только для определенного репозитория.

  • код теперь поддерживается в своем собственном реестре git

  • если приведенные выше инструкции приводят к ImportErrors, попробуйте добавить «ipython» до пути к скрипту:

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

EDIT : май 2016 года (обновлено в феврале 2017 года): есть несколько альтернатив моему сценарию - для полноты, вот список тех, кого я знаю: nbstripout ( other variants ), nbstrip , jq .


Итак, похоже, что самое лучшее в настоящее время решение, как следует из обсуждения nbstripout.py , состоит в том, чтобы сделать git-фильтр, чтобы автоматически линять вывод из ipynb-файлов при фиксации.

Вот что я сделал, чтобы заставить его работать (скопированный из этого обсуждения):

Я немного изменил файл nbstripout cfriedline, чтобы дать информативную ошибку, если вы не можете импортировать последний IPython: 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) машине.


К сожалению, я мало знаю о Mercurial, но я могу дать вам возможное решение, которое работает с Git, в надежде, что вы сможете перевести мои команды Git в их эквиваленты Mercurial.

Для фона в Git команда add сохраняет изменения, внесенные в файл в промежуточную область. После того, как вы это сделаете, любые последующие изменения в файле игнорируются Git, если вы не сообщите об этом также для их создания. Следовательно, следующий скрипт, который для каждого из данных файлов prompt_number sections все outputs и prompt_number sections , prompt_number sections разделенный файл и затем восстанавливает оригинал:

ПРИМЕЧАНИЕ. При запуске это ImportError: No module named IPython.nbformat сообщению об ошибке, например 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 .


Как указывалось выше, --script устарел в 3.x Этот подход можно использовать, применяя post-save-hook. В частности, добавьте следующее в 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 .


После того, как я начал копаться, я, наконец, нашел этот относительно простой предварительный квест на документах Jupyter . Он разделяет выходные данные ячейки. Вы должны вставить его в файл 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_notebook_config.py , вы можете ввести jupyter --config-dir [в командной строке / терминале], и если вы не найдете файл там, вы можете создать его набрав jupyter notebook --generate-config .


Чтобы следить за отличным сценарием Пьетро Баттистона, если вы получите ошибку синтаксического анализа Unicode, например:

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')

Это расширение jupyter позволяет пользователям загружать jupyter-ноутбуки непосредственно в github.

Пожалуйста, смотрите здесь

https://github.com/sat28/githubcommit


Я использую очень прагматичный подход; которые хорошо работают для нескольких ноутбуков, с нескольких сторон. И это даже позволяет мне «переносить» ноутбуки. Он работает как для Windows, так и для Unix / MacOS.
Аль думал, что это просто, решает проблемы выше ...

концепция

В принципе, не отслеживайте .ipnyb .ipnyb, только соответствующие .py файлы.
Запустив ноутбук-сервер с параметром --script , этот файл автоматически создается / сохраняется при сохранении записной книжки.

Эти .py файлы содержат все входные данные; некод сохраняется в комментариях, равно как и границы ячеек. Этот файл можно прочитать / импортировать (и перетащить) в блокнот-сервер, чтобы (повторно) создать ноутбук. Только выход пропал; пока он не будет повторно запущен.

Лично я использую меркурийные версии для отслеживания файлов .py ; и используйте обычные (командные строки) команды для добавления, check-in (ect) для этого. Большинство других (D) VCS позволит это.

Его простое отслеживание истории сейчас; .py небольшие, текстовые и простые для разграничения. Время от времени нам нужен клон (только ветка, запуск второго ноутбука) или более старая версия (проверка и импорт на ноутбук-сервер) и т. Д.

Советы и хитрости

  • Добавьте * .ipynb в ' .hgignore ', поэтому Mercurial знает, что он может игнорировать эти файлы
  • Создайте сценарий (bash) для запуска сервера (с параметром --script ) и выполните его версию
  • Сохранение ноутбука сохраняет .py -file, но не проверяет его.
    • Это недостаток : можно забыть, что
    • Это также функция : можно сохранить ноутбук (и продолжить позже) без кластеризации истории репозитория.

Пожелания

  • Было бы неплохо иметь кнопки для регистрации / добавления / etc в панели инструментов ноутбука
  • [email protected]+rev.py заказ (на пример) [email protected]+rev.py ) должно быть полезно. Было бы очень полезно добавить это; и, возможно, я сделаю это один раз. До сих пор я просто делаю это вручную.

Я создал other на основе nbstripout.py , который поддерживает Git и Mercurial (благодаря mforbes). Он предназначен для использования как автономно в командной строке, так и в виде фильтра, который легко (un) устанавливается в текущем репозитории с помощью nbstripout install / nbstripout uninstall .

Получите его от PyPI или просто

pip install nbstripout




jupyter-notebook