Come posso convertire un Notebook IPython in un file Python tramite riga di comando?


258

Sto cercando di utilizzare i file * .ipynb come fonte di verità e programmarli "compilandoli" in file .py per lavori / attività pianificati.

L'unico modo in cui capisco di farlo è tramite la GUI. C'è un modo per farlo tramite riga di comando?


1
Cosa intendi per "fonte di verità"? I notebook IPython sono solo file json. Puoi caricarli e manipolarli come dizionari Python. Per il codice sorgente dovresti iterare le inputchiavi dove cell_typeequivale a "codice". Dai un'occhiata a questo schema
theta,

1
Beh, voglio archiviare il .ipynb in un repository e non i file .py. Quindi, come "passo di costruzione", convertivo i file .ipynb in file .py per l'uso effettivo da parte del sistema automatizzato. Hai ragione, potrei semplicemente caricare il json e produrre solo le celle di codice, ma mi chiedevo se c'era già qualcosa là fuori che lo faceva già per me :)
Stefan Krawczyk,

1
@StefanKrawczyk Puoi per favore contrassegnare una risposta come accettata? Consiglierei www'siam's asnwer
pedram bashiri

Risposte:


413

Se non vuoi produrre uno script Python ogni volta che salvi, o non vuoi riavviare il kernel IPython:

Sulla riga di comando , puoi usare nbconvert:

$ jupyter nbconvert --to script [YOUR_NOTEBOOK].ipynb

Come un po 'di un trucco, puoi persino chiamare il comando sopra in un notebook IPython pre-in sospeso !(usato per qualsiasi argomento della riga di comando). All'interno di un quaderno:

!jupyter nbconvert --to script config_template.ipynb

Prima è --to scriptstata aggiunta , l'opzione era --to pythono --to=python, ma è stata rinominata nel passaggio a un sistema di notebook indipendente dalla lingua.


8
Se ne vuoi uno ogni salvataggio, jupyterpuoi attivarlo nbconverttramite hook pre o post-salvataggio: ContentsManager.pre_save_hookabd FileContentsManager.post_save_hook. Aggiungeresti un hook post-salvataggiojupyter nbconvert --to script [notebook]
jaimedash,

3
C'è un modo per fare il contrario, ovvero convertire da uno script Python a un notebook. Per esempio, avere alcuni strumenti specifici che vengono analizzati nelle celle?
Sujen Shah,

3
converti tutti i jupyter nbconvert --to script /path/to/notebooks/*.ipynb
blocchi

8
Grazie, funziona !, ma cosa succede se non voglio le # In[ ]:cose tipo nello script, voglio che sia pulito. C'è un modo per farlo?
Rishabh Agrahari,

1
@RishabhAgrahari check out qui, si può semplicemente personalizzare il linter jupyter-notebook.readthedocs.io/en/stable/extending/...
MichaelChirico

77

Se vuoi convertire tutti i *.ipynbfile dalla directory corrente allo script python, puoi eseguire il comando in questo modo:

jupyter nbconvert --to script *.ipynb

19

Ecco un modo rapido e sporco per estrarre il codice da V3 o V4 ipynb senza usare ipython. Non controlla i tipi di celle, ecc.

import sys,json

f = open(sys.argv[1], 'r') #input.ipynb
j = json.load(f)
of = open(sys.argv[2], 'w') #output.py
if j["nbformat"] >=4:
        for i,cell in enumerate(j["cells"]):
                of.write("#cell "+str(i)+"\n")
                for line in cell["source"]:
                        of.write(line)
                of.write('\n\n')
else:
        for i,cell in enumerate(j["worksheets"][0]["cells"]):
                of.write("#cell "+str(i)+"\n")
                for line in cell["input"]:
                        of.write(line)
                of.write('\n\n')

of.close()

1
La migliore risposta se non si desidera installare nessuno degli strumenti Jupyter.
Dacracot,

1
Mi piace questo. Ma ho scoperto quando scarico il formato .py dai notebook Jupyter, usa i finali di linea UNIX anche se sono su Windows. Per generare lo stesso, aggiungi il newlines='\n'terzo argomento nella chiamata al file di output aperto. (Python 3.x)
RufusVS

16

Seguendo l'esempio precedente ma con la nuova versione di nbformat lib :

import nbformat
from nbconvert import PythonExporter

def convertNotebook(notebookPath, modulePath):

  with open(notebookPath) as fh:
    nb = nbformat.reads(fh.read(), nbformat.NO_CONVERT)

  exporter = PythonExporter()
  source, meta = exporter.from_notebook_node(nb)

  with open(modulePath, 'w+') as fh:
    fh.writelines(source.encode('utf-8'))

L'ultima riga di codice, fh.writelines (source.encode ('utf-8')) fornisce 'TypeError: l'argomento write () deve essere str, non int' fh.writelines (source) funziona comunque.
BarryC,

6

Puoi farlo dall'API di IPython.

from IPython.nbformat import current as nbformat
from IPython.nbconvert import PythonExporter

filepath = 'path/to/my_notebook.ipynb'
export_path = 'path/to/my_notebook.py'

with open(filepath) as fh:
    nb = nbformat.reads_json(fh.read())

exporter = PythonExporter()

# source is a tuple of python source code
# meta contains metadata
source, meta = exporter.from_notebook_node(nb)

with open(export_path, 'w+') as fh:
    fh.writelines(source)

4

Jupytext è bello avere nella tua toolchain per tali conversioni. Permette non solo la conversione da un blocco note a uno script, ma è possibile anche tornare indietro dallo script al blocco note. E persino quel quaderno viene prodotto in forma eseguita.

jupytext --to py notebook.ipynb                 # convert notebook.ipynb to a .py file
jupytext --to notebook notebook.py              # convert notebook.py to an .ipynb file with no outputs
jupytext --to notebook --execute notebook.py    # convert notebook.py to an .ipynb file and run it 

Apparentemente c'è anche ipynb-py-convert, vedi qui .
Wayne, il

'jupytext' non è riconosciuto come comando interno o esterno, programma eseguibile o file batch. ???
Amine Chadi

Hai installato @AmineChadi. Vedi qui per come farlo. Se lo stai utilizzando tramite un notebook come interfaccia della riga di comando, puoi semplicemente eseguirlo %pip install jupytextnel tuo notebook.
Wayne,

3

Per convertire tutti i file in formato * .ipynb nella directory corrente in script Python in modo ricorsivo:

for i in *.ipynb **/*.ipynb; do 
    echo "$i"
    jupyter nbconvert  "$i" "$i"
done

3
Ho dovuto aggiungere l' --to scriptargomento per evitare l'output HTML predefinito in Jupiter 4.4.0.
trojjer,

0

Ho avuto questo problema e ho cercato di trovare la soluzione online. Sebbene abbia trovato alcune soluzioni, hanno ancora alcuni problemi, ad esempio la fastidiosa Untitled.txtcreazione automatica quando avvii un nuovo notebook dalla dashboard.

Quindi alla fine ho scritto la mia soluzione :

import io
import os
import re
from nbconvert.exporters.script import ScriptExporter
from notebook.utils import to_api_path


def script_post_save(model, os_path, contents_manager, **kwargs):
    """Save a copy of notebook to the corresponding language source script.

    For example, when you save a `foo.ipynb` file, a corresponding `foo.py`
    python script will also be saved in the same directory.

    However, existing config files I found online (including the one written in
    the official documentation), will also create an `Untitile.txt` file when
    you create a new notebook, even if you have not pressed the "save" button.
    This is annoying because we usually will rename the notebook with a more
    meaningful name later, and now we have to rename the generated script file,
    too!

    Therefore we make a change here to filter out the newly created notebooks
    by checking their names. For a notebook which has not been given a name,
    i.e., its name is `Untitled.*`, the corresponding source script will not be
    saved. Note that the behavior also applies even if you manually save an
    "Untitled" notebook. The rationale is that we usually do not want to save
    scripts with the useless "Untitled" names.
    """
    # only process for notebooks
    if model["type"] != "notebook":
        return

    script_exporter = ScriptExporter(parent=contents_manager)
    base, __ = os.path.splitext(os_path)

    # do nothing if the notebook name ends with `Untitled[0-9]*`
    regex = re.compile(r"Untitled[0-9]*$")
    if regex.search(base):
        return

    script, resources = script_exporter.from_filename(os_path)
    script_fname = base + resources.get('output_extension', '.txt')

    log = contents_manager.log
    log.info("Saving script at /%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

Per usare questo script, puoi aggiungerlo a ~/.jupyter/jupyter_notebook_config.py:)

Potrebbe essere necessario riavviare il notebook / lab jupyter affinché funzioni.


0

C'è un bel pacchetto chiamato nb_dev che è progettato per creare pacchetti Python nei Notebook di Jupyter. Come nbconvert,può trasformare un notebook in un file .py, ma è più flessibile e potente perché ha molte belle funzioni di authoring aggiuntive che ti aiutano a sviluppare test, documentazione e registrare pacchetti su PyPI. È stato sviluppato dalla gente di fast.ai.

Ha un po 'di una curva di apprendimento, ma la documentazione è buona e non è difficile nel complesso.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.