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

前端 未结 3 756
情话喂你
情话喂你 2020-12-08 22:17

I have been using \"ipython --script\" to automatically save a .py file for each ipython notebook so I can use it to import classes into other notebooks. But this recenty st

相关标签:
3条回答
  • 2020-12-08 22:51

    [UPDATED per comment by @mobius dumpling]

    Find your config files:

    Jupyter / ipython >= 4.0

    jupyter --config-dir
    

    ipython <4.0

    ipython locate profile default
    

    If you need a new config:

    Jupyter / ipython >= 4.0

    jupyter notebook --generate-config
    

    ipython <4.0

    ipython profile create
    

    Within this directory, there will be a file called [jupyter | ipython]_notebook_config.py, put the following code from ipython's GitHub issues page in that file:

    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
    

    For Jupyter, replace ipython with jupyter in check_call.

    Note that there's a corresponding 'pre-save' hook, and also that you can call any subprocess or run any arbitrary code there...if you want to do any thing fancy like checking some condition first, notifying API consumers, or adding a git commit for the saved script.

    Cheers,

    -t.

    0 讨论(0)
  • 2020-12-08 22:51

    Here is another approach that doesn't invoke a new thread (with check_call). Add the following to jupyter_notebook_config.py as in Tristan's answer:

    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
    

    Disclaimer: I'm pretty sure I got this from SO somwhere, but can't find it now. Putting it here so it's easier to find in future (:

    0 讨论(0)
  • 2020-12-08 23:06

    I just encountered a problem where I didn't have rights to restart my Jupyter instance, and so the post-save hook I wanted couldn't be applied.

    So, I extracted the key parts and could run this with 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))
    

    You can add your own bells and whistles as you would with the standard post save hook, and the config is the correct way to proceed; sharing this for others who might end up in a similar pinch where they can't get the config edits to go into action.

    0 讨论(0)
提交回复
热议问题