Ipython notebook - script устарел. Как заменить транспортом post save?

Я использую "ipython - script" для автоматического сохранения файла .py для каждого ноутбука ipython, поэтому я могу использовать его для импорта классов в другие ноутбуки. Но это последнее перестало работать, и я получаю следующее сообщение об ошибке:

`--script` is deprecated. You can trigger nbconvert via pre- or post-save hooks:
ContentsManager.pre_save_hook
FileContentsManager.post_save_hook
A post-save hook has been registered that calls:
ipython nbconvert --to script [notebook]
which behaves similarly to `--script`.

Как я понимаю, мне нужно настроить фиксацию после сохранения, но я не понимаю, как это сделать. Может кто-нибудь объяснить?

Ответ 1

[ОБНОВЛЕНО за комментарий @mobius пельмени]

Найдите ваши конфигурационные файлы:

Jupyter/ipython> = 4.0

jupyter --config-dir

ipython <4.0

ipython locate profile default

Если вам нужен новый конфиг:

Jupyter/ipython> = 4.0

jupyter notebook --generate-config

ipython <4.0

ipython profile create

В этом каталоге будет файл с именем [jupyter | ipython]_notebook_config.py [jupyter | ipython]_notebook_config.py, поместите в этот файл следующий код со страницы проблем ipython GitHub:

import os
from subprocess import check_call

c = get_config()

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

Для Jupyter замените ipython на jupyter в check_call.

Обратите внимание, что имеется соответствующий хук "pre-save", а также что вы можете вызывать любой подпроцесс или запускать любой произвольный код там... если вы хотите сделать что-то необычное, например, сначала проверить какое-то условие, уведомить потребителей API или добавить git commit для сохраненного скрипта.

Ура,

-t.

Ответ 2

Вот еще один подход, который не вызывает новый поток (с check_call). Добавьте в jupyter_notebook_config.py следующее, как в ответе Тристана:

import io
import os
from notebook.utils import to_api_path

_script_exporter = None

def script_post_save(model, os_path, contents_manager, **kwargs):
    """convert notebooks to Python script after save with nbconvert

    replaces `ipython notebook --script`
    """
    from nbconvert.exporters.script import ScriptExporter

    if model['type'] != 'notebook':
        return

    global _script_exporter
    if _script_exporter is None:
        _script_exporter = ScriptExporter(parent=contents_manager)
    log = contents_manager.log

    base, ext = os.path.splitext(os_path)
    py_fname = base + '.py'
    script, resources = _script_exporter.from_filename(os_path)
    script_fname = base + resources.get('output_extension', '.txt')
    log.info("Saving script /%s", to_api_path(script_fname, contents_manager.root_dir))
    with io.open(script_fname, 'w', encoding='utf-8') as f:
        f.write(script)

c.FileContentsManager.post_save_hook = script_post_save

Отказ от ответственности: я почти уверен, что получил это от SO somwhere, но не могу найти его сейчас. Поместите это здесь, чтобы было легче найти в будущем (:

Ответ 3

Я только что столкнулся с проблемой, когда у меня не было прав на перезапуск моего экземпляра Jupyter, и поэтому желаемый хук после сохранения не мог быть применен.

Итак, я извлек ключевые части и мог запустить это с помощью python manual_post_save_hook.py:

from io import open
from re import sub
from os.path import splitext
from nbconvert.exporters.script import ScriptExporter

for nb_path in ['notebook1.ipynb', 'notebook2.ipynb']:
    base, ext = splitext(nb_path)
    script, resources = ScriptExporter().from_filename(nb_path)
    # mine happen to all be in Python so I needn't bother with the full flexibility
    script_fname = base + '.py'
    with open(script_fname, 'w', encoding='utf-8') as f:
        # remove 'In [ ]' commented lines peppered about
        f.write(sub(r'[\n]{2}# In\[[0-9 ]+\]:\s+[\n]{2}', '\n', script))

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