Convertisseur IPython notebook vers zds markdown

a marqué ce sujet comme résolu.

Bonjour chers agrumes,

Aujourd'hui je viens proposer pour ceux que ça intéresse, moins qu'un projet, un petit script que j'ai fais hier soir en 10 minutes et qui pourrait être utile à d'autre ici. Il s'agit d'une pré-pré-pré-version d'un convertisseur d'IPython notebook vers le markdown de zds.

Si vous n'y connaissez rien à Python, lisez tout de même ça peut vous concerner tout de même car le nom est trompeur.

Qu'est ce qu'un IPython notebook ?

IPython

Un peu de contexte : IPython est un terminal interactif1 (shell) visant a remplacer l'invite de commande fournit avec la distribution standard de Python. Il apporte tout un tas de fonctionnalités et de commandes très utile à tel point que je le conseil fortement à tous ceux qui utilise Python.

Un sous projet de IPython est appelé IPython notebook. Difficile à qualifier, il s'agit d'une interface web riche à IPython. Concrètement, il s'agit d'un espace de rédaction mélangeant texte, code, images, formules… Une fois le programme lancé, un mini serveur tourne en local et vous pouvez y accéder par votre navigateur pour créer des documents. La page obtenu est alors divisé en cellule. Chaque cellule va servir de conteneur et peut contenir plusieurs types de données, principalement :

  • Du texte formaté en markdown : Une fois validé celui-ci sera transformé en html et affiché. Cela permet donc d'écrire le corps de votre texte. Il est d'ailleurs possible d'insérer des formules au format Latex
  • Du code (supposons en Python par exemple) : Une fois validé celui-ci est alors exécuté et le résultat affiché en dessous.

On arrive donc au coté pratique des notebook : il est donc possible dans un même document de mélanger texte, code et résultat et cela sans devoir faire de copier/coller entre votre éditeur de texte, votre éditeur de code et le résultat de la console. Les résultats obtenus sont sauvegardés avec le notebook ce qui permet d'avoir un document autonome et complet. Il est aussi possible de ré-éxécuter chaque cellule code (si vous choisissiez de la modifier ou parce que vous reprenez votre rédaction quelques jours après). Un petit indicateur numérique est alors placé pour précisé l'ordre dans lequel les codes sont exécutés.

En plus du texte qui est produit sur la sortie standard, le notebook est capable d'afficher directement certains éléments de bibliothèques classique de Python comme les graphique de Matplotlib ou génère des tableaux depuis les DataFrame de Pandas. Il est bien sûrs aussi possible d'insérer facilement n'importe quel image, vidéo voir en réalité tout ce qui est affichage dans un navigateur.

Une fois terminé vous pouvez exporter votre document vers du html, du pdf, etc. On obtient alors un document en lecture seul comme celui-ci.

Si vous avez un peu de temps, je vous invite a regarder cette petite vidéo de présentation, qui date un peu, mais qui vous présentera tout ça en live et bien plus (mais pensez à couper le son, la musique est horrible) :

Une présentation d'IPython notebook

Enfin notez que les IPython notebook ne sont pas limités à Python. Alors que les versions précédentes obligeaient à bidouiller pour l'utiliser avec d'autres langages, la version 3 qui ne devrait pas tarder à sortir (et que j'utilise déjà) permet de s'interfacer avec d'autres langages très facilement comme cet exemple avec Ruby, celui-ci avec Julia ou ce dernier avec Haskell.

C'est vraiment utile ? Même pour Zds ?

Peut être pas pour tout le monde, mais personnellement oui. Je l'utilise beaucoup dans le cadre de mon travail pour écrire des rapports de recherches et avoir des expériences reproductibles, avec le code et les explications au même endroit. Ce n'est aussi probablement par un hasard si Apple a présenté les Swift Playground récemment qui reprennent ce principe existant depuis de nombreuses années dans le monde Python.

Pour Zds cela peut aussi être utile. Par exemple je prépare actuellement un article et comme il mélange du texte et du code je me suis donc tourné vers IPython comme à mon habitude. Malheureusement au moment de visualiser ce que ça donnait, j'ai vite déchanté. Il fallait copier/coller chaque cellule et mettre en forme le code et les sorties pour obtenir un truc présentable. Pourtant un notebook peut faire une bonne base pour éditer un article hors-ligne, visualiser le résultat et exécuter les codes liés à l'article.

Hier soir, j'avais 10 min de temps libre et j'ai donc pondu un petit convertisseur.

cipyn.py

Après cette longue introduction je propose donc à ceux que cela interesse une pré-pré-pré version de cipyn.py, mon mini convertisseur (mini car il fait environ 60 lignes).

Pour le moment, cipyn se charge simplement d'ouvrir un notebook et de tout coller ensemble. Les cellules markdown sont reprises tel quel et les cellules de codes sont mises dans la balise dédié avec la sortie résultante si présente. Enfin les cellules de titres sont converties dans leur équivalent markdown.

Voici un exemple pour un notebook présenté plus haut :

Vous pourrez remarquer que le graphique est perdu. En effet pour le moment cela n'est pas prit en charge par le convertisseur. (je viens de rajouter l'extraction des images, voir mon post en dessous) En attendant cela permet de gagner beaucoup de temps pour passer de l'éditeur IPython à Zds.

Pour la suite

J'ai bien conscience que ce script vise une niche et que je serais, malgré mes tentatives de vous convaincre que c'est génial, le seul à utiliser IPython notebook comme éditeur offline pour Zds. Mais puisque ça peut servir, je mettrais à jour ce sujet avec les ajouts que je pourrais faire en fonction de mes besoins.

A court terme je pense ajouter la gestion des images/graphiques et probablement le rendu des des tableaux en markdown. A moyen terme, si je trouve le temps, je ferais en plus une extension pour IPython pour utiliser la feuille de style CSS du site et le remplacement du moteur markdown par le notre pour obtenir hors-ligne un éditeur totalement compatible avec ZDS et avec un rendu identique.

Voilou


  1. D'où le I de IPython 

+13 -0

Bon j'ai eu quelques minutes pour rajouter l'extraction des images (c'est moche les variables globales, je sais). J'ai donc mit a jour le sujet. Par contre ça oblige à téléverser les images manuellement et mettre a jour les sources avec le liens généré. Ça peut être pénible à la longue donc je vais peut être rajouter un "faire un outils de publication automatisé" à ma todo-list tant qu'il y a le gel de nouvelles fonctionnalités et qu'il n'y a pas de possibilités d'import complets.

Salut,

C'est sympa de voir que l'on parle du projet IPython ici!
Je l'utilise moi aussi tout les jours dans le cadre de mon travail pour lancer des mesures, traiter les résultats et rédiger des rapports. En ce moment je suis même en train de rédiger ma thèse avec! Je me suis donc penché sur les possibilités de convertion des notebooks : je convertis le notebook en un fichier markdown que je passe ensuite à pandoc pour générer le rapport dans le format qui m'intéresse (latex/pdf, html, docx, …).

Pour un convertion simple en markdown1 IPython gére déjà ça nativement. Cette ligne de commande génère un fichier "MonNotebook.md".

1
ipython nbconvert --to markdown MonNotebook.ipynb

Voici le résulat que j'obtiens avec ce notebook.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# Basic Numerical Integration: the Trapezoid Rule

A simple illustration of the trapezoid rule for definite integration:

$$
\int_{a}^{b} f(x)\, dx \approx \frac{1}{2} \sum_{k=1}^{N} \left( x_{k} - x_{k-1}
\right) \left( f(x_{k}) + f(x_{k-1}) \right).
$$

First, we define a simple function and sample it between 0 and 10 at 200 points


    %matplotlib inline
    import numpy as np
    import matplotlib.pyplot as plt


    def f(x):
        return (x-3)*(x-5)*(x-7)+85
    
    x = np.linspace(0, 10, 200)
    y = f(x)

Choose a region to integrate over and take only a few points in that region


    a, b = 1, 9
    xint = x[np.logical_and(x>=a, x<=b)][::30]
    yint = y[np.logical_and(x>=a, x<=b)][::30]

Plot both the function and the area below it in the trapezoid approximation


    plt.plot(x, y, lw=2)
    plt.axis([0, 10, 0, 140])
    plt.fill_between(xint, 0, yint, facecolor='gray', alpha=0.4)
    plt.text(0.5 * (a + b), 30,r"$\int_a^b f(x)dx$", horizontalalignment='center', fontsize=20);


![png](Trapezoid%20Rule_files/Trapezoid%20Rule_7_0.png)


Compute the integral both at high accuracy and with the trapezoid approximation


    from __future__ import print_function
    from scipy.integrate import quad, trapz
    integral, error = quad(f, 1, 9)
    print("The integral is:", integral, "+/-", error)
    print("The trapezoid approximation with", len(xint), "points is:", trapz(yint, xint))

    The integral is: 680.0 +/- 7.54951656745e-12
    The trapezoid approximation with 6 points is: 621.286411141

Tout le notebook est converti en markdown. Pour les images générées dans le notebook, elles sont converties en fichiers images, placées dans le dossier "MonNotebook_files" et insérées dans le fichier markdown avec la syntaxe ad hoc. Tout n'est pas géré mais ça fait déjà pas mal de travail. Par exemple des bloques de code python ne sont pas intégrés entre des balises ```. Là où ça devient intéressant c'est que ce mécanisme de convertion est entièrement modifiable par l'intermédiaire de templates (Jinja2 il me semble).

On peut par exemple créer un template qui met les bloques python entre des balises ```. Pour cela il suffit de créer un nouveau template "BloquePython.tpl" qui hérite d'un template interne à IPython2 et de modifier le comportement des bloques qui nous intéresse. Ici j'ai hérité du template markdown de IPython et modifié le bloque qui correspond aux "inputs" de IPython pour y ajouter les balises ``` autour.

1
2
3
4
5
6
7
8
{% extends 'markdown.tpl' %}

{% block input %}
    ```
       {{- super() }}

    ```
{% endblock input %}

A partir de là, il faut renseigner à IPython l'endroit où se trouve le template. Cette configuration est à faire dans le fichier "ipython_config.py" du profil IPython utilisé3.

1
2
3
4
5
6
7
# Configuration file for ipython.
c = get_config()

#------------------------------------------------------------------------------
# NbConvertApp configuration
#------------------------------------------------------------------------------
c.Exporter.template_path = ["/home/Devendart/Work/Python/IPythonTemplates"]

Et enfin relancer la convertion en précisant le template à utiliser :

1
ipython nbconvert --to markdown --template BloquePython MonNotebook.ipynb

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# Basic Numerical Integration: the Trapezoid Rule

A simple illustration of the trapezoid rule for definite integration:

$$
\int_{a}^{b} f(x)\, dx \approx \frac{1}{2} \sum_{k=1}^{N} \left( x_{k} - x_{k-1}
\right) \left( f(x_{k}) + f(x_{k-1}) \right).
$$

First, we define a simple function and sample it between 0 and 10 at 200 points


    ```
    %matplotlib inline
    import numpy as np
    import matplotlib.pyplot as plt

       
    ```


    ```
    def f(x):
        return (x-3)*(x-5)*(x-7)+85
    
    x = np.linspace(0, 10, 200)
    y = f(x)

       
    ```

Choose a region to integrate over and take only a few points in that region


    ```
    a, b = 1, 9
    xint = x[np.logical_and(x>=a, x<=b)][::30]
    yint = y[np.logical_and(x>=a, x<=b)][::30]

       
    ```

Plot both the function and the area below it in the trapezoid approximation


    ```
    plt.plot(x, y, lw=2)
    plt.axis([0, 10, 0, 140])
    plt.fill_between(xint, 0, yint, facecolor='gray', alpha=0.4)
    plt.text(0.5 * (a + b), 30,r"$\int_a^b f(x)dx$", horizontalalignment='center', fontsize=20);

       
    ```


![png](Trapezoid%20Rule_files/Trapezoid%20Rule_7_0.png)


Compute the integral both at high accuracy and with the trapezoid approximation


    ```
    from __future__ import print_function
    from scipy.integrate import quad, trapz
    integral, error = quad(f, 1, 9)
    print("The integral is:", integral, "+/-", error)
    print("The trapezoid approximation with", len(xint), "points is:", trapz(yint, xint))

       
    ```

    The integral is: 680.0 +/- 7.54951656745e-12
    The trapezoid approximation with 6 points is: 621.286411141

Les bloques de code python sont mainteant bien encadrés entre des balises ```.

La struture de template ouvre plein de possibilités. On peut jouer sur tout les bloques définis dans l'architecture du format notebook.

Par exemple j'ai ajouté la possibilité de renseigner des légendes aux images générées dans le notebook en utilisant les métadonnées des cellules du notebook. Pour cela j'ai développé une petite extension javascript qui permet de gérer ces métadonnées directement dans le notebook.
Il y a également un mécansime de pré-processeur qui permet de contrôler plus de chose pendant la convertion (exécuter les cellules, convertir et extraire les figures, …).

En utilisant tout ça je pense qu'on peut facilement développer une extension qui permettrait de rédiger des articles pour Zds directement sous IPython. On peut imaginer une extension JS pour gérer les bloques spéciaux comme les bloques masquées en rajoutant ces infos dans les métadonnées et un template accompagné d'éventuelles pré-processeurs pour convertir en markdown Zsd.


  1. il est aussi possible de directement convertir le notebook en latex/pdf, html, script python et même en slide html (reveal.js). 

  2. Ils sont accesible dans l'arboresence de la librairie 

  3. IPython utilise la notion de profil pour gérer plusieurs configurations (voir doc).  

Merci pour les infos. J'avais bien vu que ça permetai l'export MD direct mais je ne pensais pas qu'on pouvait gérer si finement le rendu, et comme la réalisation d'un convertisseur semblait simple....

Oui je pense que IPhython pourrait faire une bonne base pour un mini éditeur offline avec peu de modifs.

Bon courage pour ta thèse… Je compatis. Par contre tu n'a pas peur d'être un peu limité par le format ? Genre pour gérer tes références biblio ou faire des références a des tableau et/ou figure ?

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte