Wie konvertiere ich ein IPython-Notizbuch über die Befehlszeile in eine Python-Datei?

258

Ich möchte die * .ipynb- Dateien als Quelle der Wahrheit verwenden und sie programmgesteuert in .py-Dateien für geplante Jobs / Aufgaben "kompilieren".

Ich verstehe das nur über die GUI. Gibt es eine Möglichkeit, dies über die Befehlszeile zu tun?

Stefan Krawczyk
quelle
1
Was meinst du mit "Quelle der Wahrheit"? IPython-Notebooks sind nur JSON-Dateien. Sie können sie laden und als Python-Wörterbücher bearbeiten. Für den Quellcode sollten Sie inputSchlüssel iterieren , wobei cell_type"Code" gleich ist. Schauen Sie sich dieses Schema an
Theta
1
Nun, ich möchte die .ipynb in einem Repository speichern und nicht die .py-Dateien. Als 'Build-Schritt' würde ich dann die .ipynb- in .py-Dateien konvertieren, um sie vom automatisierten System tatsächlich zu verwenden. Du hast recht, ich könnte einfach den json laden und nur die Codezellen ausgeben, aber ich habe mich gefragt, ob es da draußen schon etwas gibt, das das für mich getan hat :)
Stefan Krawczyk
1
@StefanKrawczyk Kannst du bitte eine Antwort als akzeptiert markieren? Ich würde wwwilliam's asnwer empfehlen
pedram bashiri

Antworten:

413

Wenn Sie nicht jedes Mal, wenn Sie speichern, ein Python-Skript ausgeben oder den IPython-Kernel nicht neu starten möchten:

In der Befehlszeile können Sie Folgendes verwenden nbconvert:

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

Als Hack können Sie den obigen Befehl sogar in einem IPython-Notizbuch aufrufen, indem Sie ihn vorab ausstehen !(wird für jedes Befehlszeilenargument verwendet). In einem Notizbuch:

!jupyter nbconvert --to script config_template.ipynb

Vor --to scriptwurde hinzugefügt , war die Option --to pythonoder --to=python, aber es wurde umbenannt in der Entwicklung hin zu einem sprachunabhängig Notebook - System.

wwwilliam
quelle
8
Wenn Sie bei jedem Speichern einen möchten, jupyterkönnen Sie nbconvertüber Hooks vor oder nach dem Speichern auslösen : ContentsManager.pre_save_hookabd FileContentsManager.post_save_hook. Sie würden einen Haken nach dem Speichern hinzufügenjupyter nbconvert --to script [notebook]
jaimedash
3
Gibt es eine Möglichkeit, das Gegenteil zu tun, dh von einem Python-Skript in ein Notizbuch zu konvertieren? Zum Beispiel - haben Sie einige spezielle Docstrings, die in Zellen analysiert werden?
Sujen Shah
3
Konvertieren Sie alle Notizbücher in einen Ordnerjupyter nbconvert --to script /path/to/notebooks/*.ipynb
openwonk
8
Danke, es funktioniert!, Aber was ist, wenn ich nicht möchte, dass das # In[ ]:Typmaterial im Skript sauber ist? Gibt es eine Möglichkeit, das zu tun?
Rishabh Agrahari
1
@RishabhAgrahari Check out hier, können Sie einfach den Linter anpassen jupyter-notebook.readthedocs.io/en/stable/extending/…
MichaelChirico
77

Wenn Sie alle *.ipynbDateien aus dem aktuellen Verzeichnis in ein Python-Skript konvertieren möchten , können Sie den folgenden Befehl ausführen:

jupyter nbconvert --to script *.ipynb
Břetislav Hájek
quelle
19

Hier ist eine schnelle und schmutzige Möglichkeit, den Code aus V3- oder V4-Ipynb zu extrahieren, ohne Ipython zu verwenden. Es werden keine Zelltypen usw. überprüft.

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()
Valentas
quelle
1
Beste Antwort, wenn Sie keines der Jupyter-Tools installieren möchten.
Dacracot
1
Ich mag das. Aber ich habe herausgefunden, dass beim Herunterladen des .py-Formats von Jupyter-Notebooks UNIX-Zeilenenden verwendet werden, obwohl ich unter Windows arbeite. Um dasselbe zu generieren, fügen Sie das newlines='\n'dritte Argument in den Aufruf der geöffneten Ausgabedatei ein. (Python 3.x)
RufusVS
16

Nach dem vorherigen Beispiel, jedoch mit der neuen Version 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'))
Spawnrider
quelle
In der letzten Codezeile von fh.writelines (source.encode ('utf-8')) muss das Argument 'TypeError: write () str sein, nicht int'. fh.writelines (source) funktioniert jedoch.
BarryC
6

Sie können dies über die IPython-API tun.

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)
justanr
quelle
4

Jupytext ist für solche Konvertierungen gut in Ihrer Toolchain zu haben. Es ermöglicht nicht nur die Konvertierung von einem Notizbuch in ein Skript, sondern Sie können auch wieder vom Skript zum Notizbuch zurückkehren. Und sogar das Notizbuch in ausgeführter Form produzieren lassen.

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 
Wayne
quelle
Anscheinend gibt es auch ipynb-py-convert, siehe hier .
Wayne
'jupytext' wird nicht als interner oder externer Befehl, bedienbares Programm oder Batchdatei erkannt. ???
Amine Chadi
Haben Sie es @AmineChadi installiert. Sehen Sie hier , wie das zu tun. Wenn Sie es über ein Notebook als Befehlszeilenschnittstelle verwenden, können Sie es einfach %pip install jupytextin Ihrem Notebook ausführen .
Wayne
3

Zum rekursiven Konvertieren aller Dateien im * .ipynb-Format im aktuellen Verzeichnis in Python-Skripte:

for i in *.ipynb **/*.ipynb; do 
    echo "$i"
    jupyter nbconvert  "$i" "$i"
done
Don Smythe
quelle
3
Ich musste das --to scriptArgument hinzufügen , um die Standard-HTML-Ausgabe in Jupiter 4.4.0 zu vermeiden.
Trojjer
0

Ich hatte dieses Problem und versuchte online die Lösung zu finden. Obwohl ich einige Lösungen gefunden habe, haben sie immer noch einige Probleme, z. B. die lästige Untitled.txtautomatische Erstellung, wenn Sie ein neues Notizbuch über das Dashboard starten.

Also schrieb ich schließlich meine eigene Lösung :

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

Um dieses Skript zu verwenden, können Sie es hinzufügen ~/.jupyter/jupyter_notebook_config.py:)

Beachten Sie, dass Sie möglicherweise das Jupyter-Notebook / -Labor neu starten müssen, damit es funktioniert.

Jiren Jin
quelle
0

Es gibt ein sehr schönes Paket namens nb_dev , das zum Erstellen von Python-Paketen in Jupyter Notebooks entwickelt wurde. Wie nbconvert,kann es ein Notebook in eine Py - Datei drehen, aber es ist flexibler und leistungsfähiger , weil es viele nette zusätzliche Authoring hat zu helfen , Funktionen , die Sie entwickeln Tests, Dokumentation und registrieren Pakete auf PyPI. Es wurde von den fast.ai Leuten entwickelt.

Es hat eine gewisse Lernkurve, aber die Dokumentation ist gut und insgesamt nicht schwierig.

John
quelle