Comment convertir un bloc-notes IPython en fichier Python via la ligne de commande?

258

Je cherche à utiliser les fichiers * .ipynb comme source de vérité et à les «compiler» par programme dans des fichiers .py pour les tâches / tâches planifiées.

La seule façon dont je comprends cela est via l'interface graphique. Existe-t-il un moyen de le faire via la ligne de commande?

Stefan Krawczyk
la source
1
Qu'entendez-vous par «source de vérité»? Les blocs-notes IPython ne sont que des fichiers json. Vous pouvez les charger et les manipuler en tant que dictionnaires Python. Pour le code source, vous devez itérer les inputclés où cell_typeest égal à «code». Jetez un oeil à ce schéma
theta
1
Eh bien, je veux stocker le .ipynb dans un référentiel et non les fichiers .py. Ainsi, en tant qu'étape de construction, je convertirais les fichiers .ipynb en fichiers .py pour une utilisation réelle par le système automatisé. Vous avez raison, je pouvais simplement charger le json et afficher uniquement les cellules de code, mais je me demandais s'il y avait déjà quelque chose qui faisait ça pour moi :)
Stefan Krawczyk
1
@StefanKrawczyk Pouvez-vous s'il vous plaît marquer une réponse comme acceptée? Je recommanderais la réponse de wwwilliam
pedram bashiri

Réponses:

414

Si vous ne voulez pas sortir un script Python à chaque fois que vous enregistrez, ou si vous ne voulez pas redémarrer le noyau IPython:

Sur la ligne de commande , vous pouvez utiliser nbconvert:

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

Comme un peu un hack, vous pouvez même appeler la commande ci-dessus dans un bloc-notes IPython par pré-attente !(utilisée pour tout argument de ligne de commande). À l'intérieur d'un cahier:

!jupyter nbconvert --to script config_template.ipynb

Avant --to scripta été ajouté , l'option était --to pythonou --to=python, mais il a été rebaptisé en mouvement vers un système de bloc - notes langue agnostique.

wwwilliam
la source
8
Si vous en voulez une à chaque sauvegarde, jupytervous pouvez déclencher nbconvertvia des hooks avant ou après la sauvegarde: ContentsManager.pre_save_hookabd FileContentsManager.post_save_hook. Vous ajouteriez un crochet post-sauvegardejupyter nbconvert --to script [notebook]
jaimedash
3
Existe-t-il un moyen de faire l'inverse, c'est-à-dire de convertir un script python en un ordinateur portable. Par exemple, avoir des docstrings spécialisés qui sont analysés dans les cellules?
Sujen Shah
3
convertir tous les cahiers dans un dossierjupyter nbconvert --to script /path/to/notebooks/*.ipynb
openwonk
8
Merci, ça marche !, mais si je ne veux pas les # In[ ]:trucs de type dans le script, je veux que ce soit propre. Y'a-t'il un quelconque moyen d'y arriver?
Rishabh Agrahari
1
@RishabhAgrahari consultez ici, vous pouvez simplement personnaliser le linter jupyter-notebook.readthedocs.io/en/stable/extending/…
MichaelChirico
77

Si vous souhaitez convertir tous les *.ipynbfichiers du répertoire actuel en script python, vous pouvez exécuter la commande comme ceci:

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

Voici un moyen rapide et sale d'extraire le code d'ipynb V3 ou V4 ​​sans utiliser ipython. Il ne vérifie pas les types de cellules, etc.

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
la source
1
Meilleure réponse si vous ne souhaitez installer aucun des outils Jupyter.
dacracot
1
J'aime ça. Mais j'ai découvert que lorsque je télécharge le format .py à partir des blocs-notes Jupyter, il utilise des fins de ligne UNIX même si je suis sous Windows. Pour générer le même, ajoutez le newlines='\n'comme troisième argument dans l'appel de fichier de sortie ouvert. (Python 3.x)
RufusVS
16

En suivant l'exemple précédent mais avec la nouvelle version de 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'))
Spawnrider
la source
La dernière ligne de code de fh.writelines (source.encode ('utf-8')) donne 'TypeError: l'argument write () doit être str, pas int' fh.writelines (source) fonctionne cependant.
BarryC
6

Vous pouvez le faire à partir de l'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)
justanr
la source
4

Jupytext est agréable d'avoir dans votre chaîne d'outils pour de telles conversions. Il permet non seulement la conversion d'un bloc-notes en script, mais vous pouvez également revenir du script en bloc-notes. Et même faire produire ce cahier sous forme exécutée.

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
la source
Apparemment, il existe également ipynb-py-convert, voir ici .
Wayne
'jupytext' n'est pas reconnu comme une commande interne ou externe, un programme exploitable ou un fichier batch. ???
Amine Chadi
L'avez-vous installé @AmineChadi. Voir ici pour savoir comment procéder. Si vous l'utilisez via un ordinateur portable comme interface de ligne de commande, vous pouvez simplement l'exécuter %pip install jupytextdans votre ordinateur portable.
Wayne
3

Pour convertir récursivement tous les fichiers au format * .ipynb du répertoire actuel en scripts python:

for i in *.ipynb **/*.ipynb; do 
    echo "$i"
    jupyter nbconvert  "$i" "$i"
done
Don Smythe
la source
3
J'ai dû ajouter l' --to scriptargument pour éviter la sortie HTML par défaut dans Jupiter 4.4.0.
trojjer
0

J'ai eu ce problème et j'ai essayé de trouver la solution en ligne. Bien que j'aie trouvé des solutions, elles ont toujours des problèmes, par exemple, la Untitled.txtcréation automatique ennuyeuse lorsque vous démarrez un nouveau bloc-notes à partir du tableau de bord.

J'ai donc finalement écrit ma propre solution :

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

Pour utiliser ce script, vous pouvez l'ajouter à ~/.jupyter/jupyter_notebook_config.py:)

Notez que vous devrez peut-être redémarrer le cahier / laboratoire jupyter pour qu'il fonctionne.

Jiren Jin
la source
0

Il y a un très joli paquet appelé nb_dev qui est conçu pour créer des paquets Python dans les cahiers Jupyter. Commenbconvert, il peut transformer un bloc-notes en fichier .py, mais il est plus flexible et puissant car il possède de nombreuses fonctionnalités de création supplémentaires pour vous aider à développer des tests, de la documentation et à enregistrer des packages sur PyPI. Il a été développé par les gens de fast.ai.

Il a un peu de courbe d'apprentissage, mais la documentation est bonne et ce n'est pas difficile dans l'ensemble.

John
la source