ipython notebook --script 已弃用。如何替换为 post 保存钩子?

ipython notebook --script deprecated. How to replace with post save hook?

我一直在使用 "ipython --script" 为每个 ipython 笔记本自动保存一个 .py 文件,这样我就可以用它来将 类 导入其他笔记本。但是这个最近停止工作,我收到以下错误消息:

`--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`.

据我所知,我需要设置一个 post-save 挂钩,但我不知道该怎么做。有人可以解释一下吗?

[根据@mobius dumpling 的评论更新]

找到您的配置文件:

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 的文件,将 ipython's GitHub issues page 中的以下代码放入该文件中:

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,将 check_call 中的 ipython 替换为 jupyter

请注意,有一个相应的 'pre-save' 挂钩,而且您可以在那里调用任何子进程或 运行 任何任意代码...如果您想做任何花哨的事情,例如检查某些条件首先,通知 API 消费者,或为保存的脚本添加 git 提交。

干杯,

-t.

这是另一种不调用新线程的方法(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

免责声明:我很确定我是从某个地方得到这个的,但现在找不到了。放在这里方便以后查找(:

我刚遇到一个问题,我没有权限重启我的 Jupyter 实例,所以我想要的 post-save 挂钩无法应用。

所以,我提取了关键部分并且可以 运行 这个 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))

您可以像使用标准 post 保存挂钩一样添加您自己的附加功能,配置是继续进行的正确方法;与可能最终陷入类似困境但无法让配置编辑生效的其他人分享此内容。