Використання ноутбуків IPython під контролем версій


569

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

Формат ноутбука досить прихильний для контролю версій: якщо хочеться контролювати версію ноутбука та виводити, то це працює досить добре. Роздратування настає, коли хочеться лише керувати версією вводу, виключаючи вихідні клітинки (т.к. "побудувати продукти"), які можуть бути великими двійковими краплями, особливо для фільмів та сюжетів. Зокрема, я намагаюся знайти хороший робочий процес, який:

  • дозволяє мені вибирати між включенням або виключенням виводу
  • заважає мені випадково здійснити вихід, якщо я цього не хочу,
  • дозволяє зберігати вихід у моїй локальній версії,
  • дозволяє мені бачити, коли я маю зміни у входах за допомогою моєї системи управління версіями (тобто, якщо я керую лише версіями вхідними даними, але мій локальний файл має виходи, то я хотів би бачити, чи змінилися дані (що вимагає фіксації) Використання команди контролю стану версії завжди реєструє різницю, оскільки локальний файл має виходи.)
  • дозволяє мені оновлювати робочий зошит (який містить вихід) з оновленого чистого ноутбука. (оновлення)

Як було сказано, якщо я вирішив включити виходи (що бажано, наприклад, при використанні nbviewer ), то все добре. Проблема полягає в тому, що я не хочу, щоб версія контролювала вихід. Існують деякі інструменти та сценарії для зняття виводу ноутбука, але часто я стикаюся з такими проблемами:

  1. Я випадково запускаю версію з висновком, тим самим забруднюючи своє сховище.
  2. Я чіткий вихід, щоб використовувати контроль версій, але дійсно краще зберегти висновок у моїй локальній копії (іноді для відтворення, наприклад, потрібен певний час).
  3. Деякі сценарії, які виводять смужку, трохи змінюють формат порівняно з Cell/All Output/Clearопцією меню, створюючи тим самим небажаний шум у розрізниках. Це вирішено за допомогою деяких відповідей.
  4. Підтягуючи зміни до чистої версії файлу, мені потрібно знайти якийсь спосіб включення цих змін у свій робочий зошит без необхідності повторювати все. (оновлення)

Я розглянув кілька варіантів, про які я розповім нижче, але ще не знайшов хорошого комплексного рішення. Повне рішення може зажадати деяких змін у IPython або може покладатися на деякі прості зовнішні сценарії. В даний час я використовую ртутний , але хотів би рішення, яке також працює з git : ідеальним рішенням буде агностик для контролю версій.

Це питання обговорювалося багато разів, але немає остаточного чи чіткого рішення з точки зору користувача. Відповідь на це питання повинна дати остаточну стратегію. Це добре, якщо для нього потрібна остання (рівномірна розробка) версія IPython або легко встановлене розширення.

Оновлення: я грав у моїй модифікованій версії ноутбука, яка за бажанням зберігає .cleanверсію при кожному збереженні, використовуючи пропозиції Грегорі Кросвайта . Це задовольняє більшість моїх обмежень, але залишає невирішеним наступне:

  1. Це ще не стандартне рішення (вимагає модифікації джерела ipython. Чи є спосіб досягти такої поведінки простим розширенням? Потрібен якийсь гак для збереження.
  2. Проблема, яку я маю з поточним робочим процесом, - це тягне зміни. Вони надійдуть у .cleanфайл, а потім потрібно якось інтегруватись у мою робочу версію. (Звичайно, я завжди можу повторно виконати зошит, але це може бути болем, особливо якщо деякі результати залежать від довгих обчислень, паралельних обчислень тощо). Я не маю хорошого уявлення про те, як це вирішити. . Можливо, робочий процес, що включає розширення на зразок ipycache, може працювати, але це здається занадто складним.

Примітки

Видалення (зняття) виводу

  • Коли ноутбук працює, можна скористатися Cell/All Output/Clearопцією меню для видалення виводу.
  • Існує кілька сценаріїв для видалення виводу, наприклад, скрипт nbstripout.py, який видаляє вихід, але не видає такий же вихід, як за допомогою інтерфейсу ноутбука. Врешті-решт це було включено до репорта ipython / nbconvert , але це було закрито, заявляючи, що зміни тепер включені до ipython / ipython , але відповідна функціональність, здається, ще не була включена. (Оновлення) Це , як то кажуть, рішення Грегорі Crosswhite в показує , що це дуже легко зробити, навіть не вдаючись до IPython / nbconvert, тож такий підхід, ймовірно, дієвий, якщо його можна належним чином підключити. (Приєднання його до кожної системи управління версіями, однак, не здається гарною ідеєю - це має якось підключитися до механізму ноутбука.)

Групи новин

Випуски

Витягніть запити


Звучить чудова річ, яку слід додати як проблему на github.com/ipython/ipython або надіслати запит на тягу, що допоможе вам досягти цієї мети.
Кайл Келлі

4
Після того, як у вас є робочий сценарій для видалення виводу, ви можете використовувати фільтр Git "clean", щоб застосувати його автоматично перед введенням (див. Фільтри очищення / розмазання).
Маттіас

1
@foobarbecue Питання містить незадовільні способи вирішення: кожен має принаймні одне обмеження. Тепер, коли PR 4175 було об'єднано, можливо, можна сформулювати повне рішення, але це ще потрібно зробити. Як тільки у мене з’явиться певний час, я зроблю це (як відповідь), якщо хтось ще не забезпечить задовільне рішення тим часом.
mforbes

1
@saroele Я ще не знайшов рекомендованого рішення: я збирався піти з --scriptможливістю, але це було видалено. Я чекаю, коли будуть введені в життя гачки після збереження ( які заплановані ), і тоді я думаю, що зможу запропонувати прийнятне рішення, поєднуючи декілька методів.
mforbes

1
@mforbes Схоже, що PR був об'єднаний через кілька днів після вашого коментаря. Чи можете ви чи хтось більш знаючий за мене опублікувати тут відповідь, яка показує, як використовувати нову функцію?
KobeJohn

Відповіді:


124

Ось моє рішення з git. Це дозволяє просто додавати та виконувати (і відрізнятись), як зазвичай: ці операції не змінять ваше робоче дерево, і в той же час (повторне) запуск ноутбука не змінить вашу історію git.

Хоча це, ймовірно, може бути адаптоване до інших ДКС, я знаю, що воно не відповідає вашим вимогам (принаймні, агностичність 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 commit notebook_file.ipynb, хоча це хоча б не git diff notebook_file.ipynbмістить сміття base64).
  • це означає, що, до речі, якщо ви витягуєте код (тобто вчиняється кимось іншим, хто не використовує цей підхід), який містить деякий вихід, вихід перевіряється нормально. Втрачається лише місцева продукція.

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

Редагувати:

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

    **. ipynb filter =

як зміст. Зрозуміло, що таким же чином можна зробити і навпаки: включити фільтрацію лише для конкретного сховища.

  • код тепер підтримується у власному git repo

  • якщо наведені вище вказівки приводять до ImportErrors, спробуйте додати "ipython" перед шлях сценарію:

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

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


2
Як ви вирішите питання про внесення змін, які ви втягуєте? Ви просто живете з тим, щоб відновити весь результат? (Я думаю, це прояв вашого другого обмеження.)
mforbes

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,

1
Дивовижне рішення Pietro, спасибі :) Я змінив 2 речі, коли використовував ваш сценарій у моєму випадку: 1) Я вважав за краще оголосити фільтр у .gitattributes у корені репо, на відміну від ~/.gitattributes, у інших людей є ті ж фільтри, що і у мене 2 ) Я визначив regexp як workdir/**/*.ipynb filter=dropoutput_ipynb, і я розміщую більшість своїх зошитів у workdir / => якщо я все-таки хочу натиснути ноутбук з результатом і насолоджуватися відмітним відображенням у github, я просто поклав його за межі цієї папки.
Svend

63

У нас є спільний проект, де продуктом є «Блокноти Юпітера», і ми використовуємо підхід протягом останніх шести місяців, який працює чудово: ми активуємо .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

У Ipython 3.x --scriptзастарілий. ipython.org/ipython-doc/3/whatsnew/version3.html
Дрор

Дякую @dror, я оновив свою відповідь, щоб забезпечити рішення ipithon 3.x від minrk, як ви також надали тут.
Rich Signell

10
Оновлення: це рішення порушено в версії iPython 4, через "Великий спліт" Юпітера від iPython. Щоб налаштувати це рішення до версії 4, використовуйте команду jupyter notebook --generate-configдля створення конфігураційного файла. Команда jupyter --config-dirвизначає, який каталог містить конфігураційні файли. І фрагмент коду, наданий @Rich, слід додати до імені файлу jupyter_notebook_config.py. Решта працює як і раніше.
mobius dumpling

2
На додаток до точки по @mobiusdumpling, замініть check_call(['ipython'з check_call(['jupyter', в іншому випадку ви отримаєте попередження про те , ipython nbconvertє застарілим , і ви повинні використовувати jupyter nbconvertзамість цього. (Jupyter v4.1.0, iPython v4.1.2)
cutculus

36

Я створив nbstripout, базуючись на суті MinRKs , яка підтримує як Git, так і Mercurial (завдяки mforbes). Він призначений для використання або в окремому командному рядку, або як фільтр, який легко (не) встановлюється в поточному сховищі через nbstripout install/ nbstripout uninstall.

Отримайте його з PyPI або просто

pip install nbstripout

Я розглядаю робочий процес, у якому я зберігаю як .ipynb, так і відповідні .py автоматично створені за допомогою описаних вище гачків для збереження. Я хотів би використовувати .py для diff - чи nbstripout зможе очистити файл .py з лічильників виконання комірок (# In [1] змінено на In [*]), щоб вони не захаращували розрізки або мені слід створити простий сценарій для цього?
Krzysztof Słowiński

1
@ KrzysztofSłowiński Ні, nbstripoutця версія використання не підтримується легко, оскільки вона покладається на формат JSON Notebook. Ви, ймовірно, краще написати сценарій, спеціалізований для вашого випадку використання.
кинан

13

Ось нове рішення від Cyrille Rossant для IPython 3.0, яке зберігається для розмітки файлів, а не ijsmd-файлів на основі json:

https://github.com/rossant/ipymd


Здається, ще не підтримує Юпітера.
К.-Майкл Айе

Я успішно використовую ipymd з останнім Jupyter - чи отримуєте ви якусь конкретну проблему чи повідомлення про помилку?
Кирила Россант

13

Після кількох років вилучення вихідних записів у ноутбуках я спробував придумати краще рішення. Зараз я використовую Jupytext , розширення як для ноутбука Jupyter, так і для лабораторії Jupyter, яке я створив.

Jupytext може конвертувати ноутбуки Юпітера в різні текстові формати (Сценарії, Маркдаун та R Маркдаун). І навпаки. Він також пропонує можливість з’єднати ноутбук в одному з цих форматів і автоматично синхронізувати два представлення ноутбука ( .ipynbі .md/.py/.Rфайл).

Дозвольте пояснити, як Юпітекст відповідає на вищезазначені питання:

дозволяє мені вибирати між включенням або виключенням виводу

.md/.py/.RФайл містить тільки вхідні осередки. Ви завжди повинні відслідковувати цей файл. Версію .ipynbфайлу слід лише в тому випадку, якщо ви хочете відстежувати результати.

заважає мені випадково здійснити вихід, якщо я цього не хочу,

Додати *.ipynbв.gitignore

дозволяє зберігати вихід у моїй локальній версії,

Вихідні дані зберігаються у (локальному) .ipynbфайлі

дозволяє мені бачити, коли я маю зміни у входах за допомогою моєї системи управління версіями (тобто, якщо я керую лише версіями вхідними даними, але мій локальний файл має виходи, то я хотів би бачити, чи змінилися дані (що вимагає фіксації) Використання команди контролю стану версії завжди реєструє різницю, оскільки локальний файл має виходи.)

Розділення на файл .py/.Rабо .mdфайл - це те, що ви шукаєте

дозволяє мені оновлювати робочий зошит (який містить вихід) з оновленого чистого ноутбука. (оновлення)

Перетягніть останню версію файлу .py/.Rабо .mdфайлу та оновіть свій ноутбук у Jupyter (Ctrl + R). Ви отримаєте останні текстові клітинки з текстового файлу з відповідними результатами з .ipynbфайлу. Ядро не впливає, це означає, що ваші локальні змінні збереглися - ви можете продовжувати працювати там, де ви його залишили.

Що я люблю в Jupytext, це те, що ноутбук (у формі .py/.Rабо .mdфайлу) можна редагувати у вашому улюбленому IDE. При такому підході рефакторинг ноутбука стає простим. Коли ви закінчите, вам просто потрібно оновити ноутбук у Юпітері.

Якщо ви хочете спробувати: встановіть за допомогою Jupytext pip install jupytextта перезапустіть редактор Jupyter Notebook або Lab editor. Відкрийте блокнот, на якому ви хочете керувати версіями, і з'єднайте його у файл Markdown (або сценарій), використовуючи меню Jupytext у блокноті Юпітера (або команди Jupytext в лабораторії Юпітера). Збережіть свій ноутбук, і ви отримаєте два файли: оригінал .ipynb, плюс обіцяне подання тексту ноутбука, що ідеально підходить для контролю версій!

Для тих, хто може бути зацікавлений: Jupytext також доступний у командному рядку .


13

Оновлення : Тепер ви можете редагувати файли ноутбука Jupyter безпосередньо у Visual Studio Code. Ви можете редагувати ноутбук або перетворений файл python.

Нарешті я знайшов продуктивний і простий спосіб змусити Юпітера та Гіта чудово грати разом. Я все ще перебуваю на перших кроках, але я вже вважаю, що це набагато краще, ніж усі інші складні рішення.

Visual Studio Code - це класний і відкритий редактор коду від Microsoft. Він має відмінне розширення Python, що дозволяє вам імпортувати ноутбук Юпітер як код python. Тепер ви також можете безпосередньо редагувати ноутбуки Юпітера .

Після того, як ви імпортуєте ваш ноутбук у файл python, весь код і розмітка буде разом у звичайному файлі python, із спеціальними маркерами у коментарях. Ви можете побачити на зображенні нижче:

Редактор VSCode з ноутбуком, перетвореним на python

Ваш файл python просто містить вміст комірок для введення ноутбука. Вихід буде створений у розділеному вікні. Ви маєте чистий код у зошиті, він не змінюється, коли ви просто виконайте його. Немає змішаного виводу з вашим кодом. Не дивний незрозумілий JSON формат для аналізу ваших розбіжностей.

Просто чистий код пітона, за яким ви можете легко ідентифікувати кожну різницю.

Мені навіть більше не потрібно версувати свої .ipynbфайли. Я можу поставити *.ipynbрядок .gitignore.

Потрібно створити зошит, щоб опублікувати або поділитися з кимось? Немає проблем, просто натисніть кнопку експорту в інтерактивному вікні пітона

Експорт файлу python у формат Notebook

Якщо ви редагуєте ноутбук безпосередньо, тепер з’явився значок Convert and save to a python script. Піктограми Юпітера у коді Visual Studio

Ось скріншот ноутбука в коді Visual Studio:

Редагування ноутбука всередині VSCode

Я використовую його лише день, але нарешті я можу із задоволенням використовувати Юпітер разом з Git.

PS: Завершення коду VSCode набагато краще, ніж Юпітер.


12

(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

інструменти


11

Дуже популярні відповіді 2016 року - це непослідовні хаки порівняно з кращим способом зробити це у 2019 році.

Існує кілька варіантів, найкращим, що відповідає на питання, є 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 року)

Потік рішення для вибору стратегії контролю версій


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файлу до ноутбука проблематично, тому це, на жаль, не є повним рішенням. (Я б хотів, щоб це було, як це дуже приємно розрізняти .pyфайли замість ноутбуків. Можливо, нова функція diff ноутбука буде корисною.
mforbes

1
Дякую! Зараз я використовую цей трюк для відтворення --scriptповедінки, незалежно від контролю версій. Спочатку у мене виникли деякі проблеми, тому на всякий випадок я можу врятувати когось деякий час: 1) Якщо ipython_notebook_config.pyвідсутня в папці профілю, запустіть, ipython profile createщоб створити її. 2) Якщо здається, що гачок після збереження ігнорується, запустіть ipython --debugдля діагностики проблеми. 3) Якщо сценарій з помилкою ImportError: No module named mistune- просто встановити minstue: pip install mistune.
Джо

7

На жаль, я не знаю багато про Mercurial, але можу запропонувати вам можливе рішення, яке працює з Git, сподіваючись, що ви зможете перевести мої команди Git у їх еквіваленти Mercurial.

Для фону, в Git addкоманда зберігає зміни, внесені до файлу, в область постановки. Після цього Git ігнорує будь-які наступні зміни у файлі, якщо ви не наказате йому також їх поетапно. Отже, наступний скрипт, який для кожного із заданих файлів викреслює всі outputsта prompt_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 (хоча для цього можна використовувати чергові черги ). Тим часом я спробував додати цей код до гачка збереження, що зберігає чисту версію з .cleanрозширенням. На жаль, мені не вдалося зрозуміти, як це зробити, не змінюючи безпосередньо IPython (хоча ця зміна була досить тривіальною). Я пограю з цим деякий час і побачу, чи відповідає він усім моїм потребам.
mforbes

6

Я використовую дуже прагматичний підхід; які добре працюють для декількох зошитів, з декількох сторін. І це навіть дозволяє мені «переносити» зошити навколо. Він працює як для Windows, так і для Unix / MacOS.
Але думав, що це просто, це вирішити проблеми вище ...

Концепція

В основному, не відслідковуйте .ipnyb-файли, лише відповідні .py-файли.
При запуску ноутбука-сервера з --scriptопцією, то цей файл буде автоматично створений / збережений , коли ноутбук буде збережений.

Ці .pyфайли містять усі дані; не-код зберігається в коментарях, як і рамки комірок. Цей файл можна прочитати / імпортувати (та перетягнути) на сервер ноутбуків для (повторного) створення блокнота. Тільки вийшов вихід; поки її не запустять.

Особисто я використовую mercurial для відстеження версій .pyфайлів; і використовуйте звичайні команди (командний рядок) для додавання, реєстрації (ect) для цього. Більшість інших (D) VCS дозволить це зробити.

Просте відстеження історії зараз; .pyмаленькі, текстові і просто дифф. Раз у раз нам потрібен клон (просто відділення; запустити там другий зошит-север) або старіша версія (перевірити його та імпортувати на ноутбук-сервер) тощо.

Поради та рекомендації

  • Додайте * .ipynb до ' .hgignore ', щоб Mercurial знав, що може ігнорувати ці файли
  • Створіть (bash) скрипт, щоб запустити сервер (з --scriptопцією) і зробити версію-відстежити його
  • Збереження ноутбука зберігає .py-файл, але не перевіряє його.
    • Це недолік : можна це забути
    • Це також особливість : Можна зберегти ноутбук (і продовжити пізніше) без кластеризації історії сховищ.

Побажання

  • Було б непогано мати кнопки для реєстрації / додати / тощо на панелі приладів ноутбука
  • Оформлення замовлення (на прикладі) file@date+rev.pyповинно бути корисним. Доповнити це було б великою роботою; і, можливо, я зроблю це колись. До сих пір я це просто роблю вручну.

Як перейти від .pyфайлу назад до зошита? Мені подобається такий підхід, але оскільки .ipynb-> .py-> .ipynbпотенційно втрачає, я не сприймав це серйозно.
mforbes

Це легко: завантажте його, наприклад, опустивши його на де-панель ноутбуків. За винятком "вихідних даних" нічого не втрачається
Альберт

Якщо це правда, то я думаю , що це було б близько до ідеї, але я , здається, нагадає , що IPython не зробили ніяких зобов'язань повністю збереження даних при переході від .pyдо .ipynbформатам. Про це є питання - тому, можливо, це стане основою для повного вирішення.
mforbes

У мене є складне перетворення .pyфайлів у .ipynbфайли. nbconvertСхоже, це ще не підтримує, і у мене немає інформаційної панелі ноутбука, оскільки я працюю ipython notebookвручну. Чи є якісь загальні пропозиції щодо здійснення цього зворотного перетворення?
mforbes

Безумовно, .pyперетворення на-ноутбук не призначене для обороту. Тож це насправді не може бути загальним рішенням, хоча приємно, що воно працює для вас.
holdenweb

3

Щоб продовжити виконання відмінного сценарію Pietro Battiston, якщо ви отримаєте помилку розбору 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')

3

Я створив пакет python, який вирішує цю проблему

https://github.com/brookisme/gitnb

Він надає CLI синтаксисом, навіяним git, для відстеження / оновлення / відмінності ноутбуків всередині вашого git repo.

Ось приклад

# 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_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

З відповіді Річ Сіньелла :

Якщо ви не впевнені, в якому каталозі знайти свій 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файл не дуже вдалий вибір, якщо ноутбук - це в першу чергу код Юлії! Нарешті, --scriptзастаріла, тому я думаю, що гачки - це шлях.
mforbes

Рішення фільтра git у вашому посиланні добре, ви повинні скопіювати свою відповідь звідси :-)
mcarans

2

Гаразд, так це виглядає як поточне найкраще рішення, відповідно до обговорення тут , - це зробити фільтр 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).


1

Це розширення для юпітерів дозволяє користувачам натискати ноутбуки з юпітером безпосередньо на github.

Будь ласка, подивіться тут

https://github.com/sat28/githubcommit


чи можете ви пояснити, що це робить? Дументація не особливо чітка.
Алекс Монрас

@AlexMonras Це безпосередньо додасть кнопку в зошиті юпітера, звідки ви зможете натиснути ноутбуки до свого репортажу GitHub із повідомленням про фіксацію
сб

1

Це квітень-2020, і існує безліч стратегій та інструментів для контролю версій ноутбука Юпітер. Ось короткий огляд усіх інструментів, які ви можете використовувати,

  • nbdime - Приємно для локального розмежування та об’єднання ноутбуків

  • nbstripout - фільтр git для автоматичного видалення виходів ноутбука перед кожним фіксацією

  • jupytext - Зберігає .py-супровідний файл, синхронізований із кожним ноутбуком. Ви вводите лише файли .py

  • nbconvert - Перетворення ноутбуків у скрипт python або HTML (або обидва) та виконувати ці альтернативні типи файлів

  • ReviewNB - Показує, що ноутбук відрізняється (разом з результатом) для будь-якого запиту на комісію або тягнення на GitHub. Можна також писати коментарі на комірки ноутбука, щоб обговорити зміни (знімок екрана нижче).

введіть тут опис зображення

Відмова: Я створив ReviewNB.


0

Як щодо ідеї, обговореної в публікації нижче, де слід зберігати вихід ноутбука, аргументуючи це тим, що їх генерування може зайняти тривалий час, і це зручно, оскільки GitHub тепер може робити ноутбуки. Для експорту файлу .py додано гачки для автоматичного збереження, які використовуються для diff та .html для обміну з членами команди, які не використовують ноутбуки чи git.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.