Jak przekonwertować notes IPython na plik Python za pomocą wiersza polecenia?


258

Patrzę na wykorzystanie plików * .ipynb jako źródła prawdy i programowe „kompilowanie” ich w pliki .py dla zaplanowanych zadań / zadań.

Jedyny sposób, w jaki to rozumiem, to GUI. Czy można to zrobić za pomocą wiersza polecenia?


1
Co rozumiesz przez „źródło prawdy”? Notatniki IPython to tylko pliki Json. Możesz je ładować i manipulować jako słowniki Pythona. W przypadku kodu źródłowego powinieneś iterować inputklucze, w których cell_typerówna się „kod”. Spójrz na ten schemat
theta

1
Cóż, chcę przechowywać .ipynb w repozytorium, a nie w plikach .py. Więc jako „krok kompilacji” przekonwertowałbym .ipynb na pliki .py do faktycznego wykorzystania przez zautomatyzowany system. Masz rację, mogłem po prostu załadować JSON i wyprowadzić tylko komórki kodu, ale zastanawiałem się, czy jest już coś, co to dla mnie zrobiło :)
Stefan Krawczyk

1
@StefanKrawczyk Czy możesz oznaczyć odpowiedź jako zaakceptowaną? Poleciłbym odpowiedź wwwilliam
pedram bashiri

Odpowiedzi:


413

Jeśli nie chcesz wypisywać skryptu Python przy każdym zapisywaniu lub nie chcesz restartować jądra IPython:

W wierszu polecenia możesz użyć nbconvert:

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

W ramach odrobiny włamania możesz nawet wywołać powyższe polecenie w notatniku IPython , wstępnie oczekując !(używane dla dowolnego argumentu wiersza poleceń). Wewnątrz notatnika:

!jupyter nbconvert --to script config_template.ipynb

Zanim --to scriptzostała dodana opcja był --to pythonalbo --to=python, ale został przemianowany w kierunku stworzenia systemu językowego notebook-agnostykiem.


8
Jeśli chcesz po jednym zapisaniu, jupytermożesz uruchomić nbconvertza pomocą haków przed zapisaniem lub po zapisaniu: ContentsManager.pre_save_hookabd FileContentsManager.post_save_hook. jupyter nbconvert --to script [notebook]
Dodałbyś

3
Czy istnieje sposób na wykonanie czynności odwrotnej, tj. Konwersję ze skryptu Pythona na notatnik. Na przykład - mając jakieś wyspecjalizowane dokumenty, które są parsowane do komórek?
Sujen Shah

3
przekonwertuj wszystkie zeszyty w folderzejupyter nbconvert --to script /path/to/notebooks/*.ipynb
openwonk

8
Dzięki, działa !, ale co, jeśli nie chcę # In[ ]:pisania w skrypcie, chcę, żeby był czysty. Czy istnieje jakiś sposób, aby to zrobić?
Rishabh Agrahari

1
@RishabhAgrahari sprawdzić tutaj, można po prostu dostosować LINTER jupyter-notebook.readthedocs.io/en/stable/extending/...
MichaelChirico

77

Jeśli chcesz przekonwertować wszystkie *.ipynbpliki z bieżącego katalogu na skrypt Pythona, możesz uruchomić następującą komendę:

jupyter nbconvert --to script *.ipynb

19

Oto szybki i brudny sposób na wyodrębnienie kodu z ipynb V3 lub V4 bez użycia ipython. Nie sprawdza typów komórek itp.

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
Najlepsza odpowiedź, jeśli nie chcesz instalować żadnego z narzędzi Jupyter.
dacracot

1
Lubię to. Ale dowiedziałem się, kiedy pobieram format .py z notesów Jupyter, używa on końcówek linii UNIX, mimo że jestem w systemie Windows. Aby wygenerować to samo, dodaj newlines='\n'jako trzeci argument w wywołaniu otwartego pliku wyjściowego. (Python 3.x)
RufusVS

16

Zgodnie z poprzednim przykładem, ale w nowej wersji lib nbformat :

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'))

ostatni wiersz kodu, fh.writelines (source.encode ('utf-8')) daje 'TypeError: write () argument musi być str, a nie int' fh.writelines (source) działa.
BarryC

6

Możesz to zrobić z interfejsu API 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 dobrze jest mieć w swoim łańcuchu narzędzi do takich konwersji. Pozwala to nie tylko na konwersję ze notesu na skrypt, ale także na powrót ze skryptu do notatnika. I nawet ten notebook został wyprodukowany w formie wykonanej.

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 

Najwyraźniej istnieje również ipynb-py-convert, patrz tutaj .
Wayne

„jupytext” nie jest rozpoznawany jako wewnętrzna lub zewnętrzna komenda, program operacyjny lub plik wsadowy. ???
Amine Chadi

Czy zainstalowałeś go @ AmineChadi? Zobacz tutaj, jak to zrobić. Jeśli używasz go za pomocą notebooka jako interfejsu wiersza poleceń, możesz po prostu uruchomić %pip install jupytextw swoim notatniku.
Wayne

3

Aby przekonwertować rekurencyjnie wszystkie pliki w formacie * .ipynb w bieżącym katalogu na skrypty python:

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

3
Musiałem dodać --to scriptargument, aby uniknąć domyślnego wyjścia HTML w Jupiter 4.4.0.
trojjer

0

Miałem ten problem i próbowałem znaleźć rozwiązanie online. Chociaż znalazłem pewne rozwiązania, nadal mają pewne problemy, np. Irytujące Untitled.txtautomatyczne tworzenie, gdy uruchamiasz nowy notatnik z deski rozdzielczej.

W końcu napisałem własne rozwiązanie :

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

Aby użyć tego skryptu, możesz dodać go do ~/.jupyter/jupyter_notebook_config.py:)

Pamiętaj, że może być konieczne ponowne uruchomienie notebooka / laboratorium jupyter, aby działało.


0

Istnieje bardzo ładny pakiet o nazwie nb_dev, który jest przeznaczony do tworzenia pakietów Pythona w notesach Jupyter. Podobnie nbconvert,jak może przekształcić notebooka w plik .py, ale jest bardziej elastyczny i wydajny, ponieważ ma wiele fajnych dodatkowych funkcji tworzenia, które pomagają opracowywać testy, dokumentację i rejestrować pakiety na PyPI. Został opracowany przez ludzi fast.ai.

Ma trochę krzywej uczenia się, ale dokumentacja jest dobra i ogólnie nie jest trudna.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.