Save ipython notebook as script programmatically

2019-02-15 10:13发布

问题:

The excellent ipython notebook has a handy --script command line flag that automatically saves a copy of the notebook as a .py script file (removing any header and markdown cells). Is there a way to switch this feature on from inside the notebook itself after the notebook is opened? Apparently, this option is not accessible to the %config magic.

Is there a way to have a cell that does this conversion? Is there any command-line tool I could use to do the conversion, and just have that in a shell command run from the notebook? (It seems that nbconvert does not output to .py.)

The reason I ask is that I have a git repository of notebooks, and I need to make sure the .py files are kept up to date when users change the notebooks themselves because the .py files are used to create c++ code from the contents of the notebooks. But I can't rely on users to set the --script flag because they'll always forget. (And I include myself in that group of users.)

回答1:

Better yet (at least for my purposes): ipython respects local copies of the ipython_notebook_config.py file. So I can just add

c = get_config()
c.NotebookManager.save_script = True

to such a file in my notebook directory. Apparently, ipython first reads ~/.ipython/profile_default/ipython_notebook_config.py, and then reads the local copy of that file. So it's safe to use without worrying about demolishing the user settings.

This was not at all clear to me from the documentation, but I just tried it and it worked.



回答2:

Oh. My mistake. nbconvert can handle conversions to script. So I can do something like this:

!ipython nbconvert --to python MyNB.ipynb

Of course, this line will get saved to the script, which means the script will try to re-save the notebook to itself every time it's executed. That's a bit circular, and I can imagine it could cause problems with some of my more outlandish hacks. Instead, we can ensure that it's only run from ipython by wrapping it as follows:

try :
    if(__IPYTHON__) :
        !ipython nbconvert --to python MyNB.ipynb
except NameError :
    pass

Note that the conversion process will automatically convert the ! syntax to something that is acceptable to plain python. This is apparently not the case with the --script conversion. So the extra-safe way to do this is

try :
    if(__IPYTHON__) :
        get_ipython().system(u'ipython nbconvert --to python MyNB.ipynb')
except NameError :
    pass