Last chance! 50% off DataCamp Premium
Sale ends in
Nel data science capita spesso di dover creare report del tuo lavoro da mostrare ai decisori o ad altre persone non tecniche. Convertire il tuo Jupyter Notebook in un documento PDF o HTML stabile è più facilmente condivisibile con i colleghi che non hanno Python o Jupyter installato. Python usa una libreria chiamata nbconvert e un linguaggio di templating chiamato Jinja2 per la conversione dei documenti. I template definiscono come un documento verrà visualizzato su una pagina web o in un altro formato di output. Capire come personalizzare i template è utile per creare report curati dei tuoi Notebook.
I Jupyter notebook sono un modo per eseguire codice Python nel browser. Se vuoi saperne di più su Python, dai un'occhiata al nostro corso gratuito Intro to Python for Data Science.
In questo tutorial tratterai i seguenti argomenti:
Jinja2.nbconvert per esportare i tuoi Notebook.Dal wiki di Python: "Il templating, e in particolare il web templating, è un modo per rappresentare i dati in forme diverse... Spesso, le soluzioni di templating coinvolgono un documento (il template) e i dati. I template di solito assomigliano molto all'output finale, con segnaposto al posto dei dati reali"
Il Jupyter Notebook può essere esportato facilmente usando File -> Download As (in JupyterLab vedrai Export Notebook As). Questa opzione usa i template predefiniti presenti nell'ambiente principale di Jupyter. Jinja2 è un potente linguaggio di templating per Python per definire blocchi e impaginazione. I template hanno sezioni, definite da tag, che indicano al template come renderizzare i dati in input. I dati sostituiscono le variabili o le espressioni quando il template viene renderizzato.
I delimitatori per le diverse sezioni di un template sono:
{% ... %} per le Statement{{ ... }} per le Expressions da stampare nell'output del template{# ... #} per i Comment non inclusi nell'output del templateDai un'occhiata a questo breve esempio di template Jinja (tratto dalla documentazione di Jinja2):
<!DOCTYPE html>
<html lang="en">
<head>
{% block head %}
<link rel="stylesheet" href="style.css" />
<title>{% block title %}{% endblock %} - My Webpage </title>
{% endblock %}
</head>
<body>
<div id="content">{% block content %}{% endblock %}</div>
<div id="footer">
{% block footer %}
© Copyright 2008 by <a href="http://domain.invalid">you </a>.
{% endblock %}
</div>
</body>
</html>
Come puoi vedere, gran parte del template assomiglia a un normale documento HTML. Jinja ha bisogno di qualche riga in più per interpretare il codice come template. Il {% block head %} definisce la sezione head del documento HTML e come questo template ne estenderà la formattazione. La sezione {% block title %} descrive dove verrà visualizzato il titolo in input. E {% endblock %} compare in più punti perché chiude il blocco di template corrispondente.
Ora sei pronto per imparare a usare Jinja per creare template personalizzati!
Jinja è un motore di templating che ti permette di definire come verranno visualizzati i tuoi documenti. In particolare, in questo tutorial ti concentrerai su come esportare il tuo Jupyter Notebook con l'aiuto dei template Jinja.
Per prima cosa, importa Template da Jinja2:
from jinja2 import Template
Renderizzare i dati nei template Jinja è piuttosto semplice. Usando parentesi e nomi di variabili, puoi mostrare i tuoi dati nel template:
myTemplate = Template("My template is {{ something }}!")
myTemplate.render(something="awesome")
'My template is awesome!'
Chiamando .render(input) puoi visualizzare il template nel tuo Notebook con il tuo input che sostituisce il generico {{ something }} del template. Questo è un esempio di uso di una expression in Jinja.
Puoi usare un template in modo più dinamico definendo una statement in Python, che Jinja interpreterà.
myFancyTemplate = Template("Let's count to 10: {% for i in range(11) %}{{i}} " "{% endfor %}")
myFancyTemplate.render()
"Let's count to 10: 0 1 2 3 4 5 6 7 8 9 10 "
Nota: hai definito un ciclo for e il template ha renderizzato i numeri da 0 a 10 separati da spazi. La sintassi della statement {% expression %} offre molta flessibilità per creare un template personalizzato.
Per creare template che estendano gli export predefiniti di Jupyter, puoi usare l'ereditarietà dei template. L'ereditarietà è il concetto in programmazione per cui puoi implementare qualcosa in un oggetto figlio sfruttando la funzionalità definita dal genitore. Un esempio semplice: se hai un oggetto Dog che può abbaiare, mangiare e camminare, puoi usare l'ereditarietà per creare un oggetto Dalmatian che erediti tutti quegli attributi e ne aggiunga altri, come ha le macchie. In questo tutorial vedrai quanto l'ereditarietà sia utile per il templating, perché in genere servono solo piccole modifiche per personalizzare l'output. Come in altri linguaggi con ereditarietà, Jinja usa parole chiave come extends e super per accedere alle definizioni del genitore.
Guarda l'esempio di template genitore qui sopra, chiamato base.html:
<!DOCTYPE html>
<html lang="en">
<head>
{% block head %}
<link rel="stylesheet" href="style.css" />
<title>{% block title %}{% endblock %} - My Webpage </title>
{% endblock %}
</head>
<body>
<div id="content">{% block content %}{% endblock %}</div>
<div id="footer">
{% block footer %}
© Copyright 2008 by <a href="http://domain.invalid">you </a>.
{% endblock %}
</div>
</body>
</html>
Un template figlio potrebbe essere così (tratto dalla documentazione di Jinja2):
{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
{{ super() }}
<style type="text/css">
.important { color: #336699; }
</style>
{% endblock %}
{% block content %}
<h1>Index</h1>
<p class="important">
Welcome to my awesome homepage.
</p>
{% endblock %}
Nota come il template figlio inizi con {% extends "base.html" %}. Questa dichiarazione dice al motore di templating Jinja come trattare questo documento (come HTML con ereditarietà da base.html). Usare questo template figlio consente di specificare attributi diversi per la homepage (come un colore CSS specifico). Inoltre, puoi vedere nel blocco head che il template figlio eredita lo stile del genitore con la chiamata a super().
Ora che hai capito la sintassi di base e l'ereditarietà dei template, puoi imparare a esportare il tuo Jupyter Notebook con nbconvert e a definire template per personalizzare l'output.
Per prima cosa importa nbconvert:
import nbconvert
nbconvert può creare output in vari formati. Questo tutorial si concentrerà su output HTML e LaTeX/PDF. Per visualizzare l'output nel notebook, usa la funzione di display di IPython e l'opzione --stdout nella chiamata a nbconvert.
example = !jupyter nbconvert --to html 'Example.ipynb' --stdout
from IPython.display import HTML, display
display(HTML('\n'.join(example)))
[NbConvertApp] Converting notebook Example.ipynb to html

Questo estratto di un Notebook è molto simile al file .ipynb originale. L'output viene visualizzato come documento autonomo con intestazioni e testo come normalmente in un Notebook. I blocchi di celle di codice sono mostrati come riquadri grigi (il cosiddetto "Notebook style"). La principale differenza visibile è che il template HTML predefinito di Jupyter non mostra i prompt "Out:", come fanno i Notebook attivi.
In genere, vorrai estendere i template di esportazione predefiniti di Jupyter Notebook e apportare piccole modifiche di design al tuo output.
Per esempio, guarda questo semplice template che rimuove le celle Markdown dall'output (chiamato rmMkdwn.tpl):
{% extends 'basic.tpl'%}
{% block markdowncell -%}
{% endblock markdowncell %}
Applicare un template a nbconvert si fa con l'opzione --template=:
example = !jupyter nbconvert --to html 'Example.ipynb' --template='rmMkdwn.tpl' --stdout
display(HTML('\n'.join(example)))
[NbConvertApp] Converting notebook Example.ipynb to html
Anche un template molto semplice, come rmMkdwn.tpl, può aiutarti a personalizzare enormemente il tuo output.
Guarda questo template più complesso, che incornicia le celle in rosso (chiamato boxRed.tpl):
{% extends 'full.tpl'%}
{% block any_cell %}
<div style="border:thin solid red">
{{ super() }}
</div>
{% endblock any_cell %}
example = !jupyter nbconvert --to html 'Example.ipynb' --template='boxRed.tpl' --stdout
display(HTML('\n'.join(example)))
[NbConvertApp] Converting notebook Example.ipynb to html 
Qui sopra puoi vedere che l'unica modifica di stile sono i riquadri rossi attorno a ciascuna cella. super() viene usato per assicurare che ogni cella mantenga il proprio stile individuale dal template genitore full.tpl.
Poiché { } e % sono caratteri speciali in LaTeX, devi usare (( )) e *. Inoltre i template LaTeX predefiniti sono base.tplx, article.tplx e report.tplx, che corrispondono alle classi di documento LaTeX.
Vediamo come rimuovere le celle Markdown con un template figlio LaTeX:
((* extends 'article.tplx' *))
((* block markdowncell -*))
((* endblock markdowncell *))
nbconvert può generare output LaTeX o PDF: l'output PDF è compilato a partire dai template LaTeX. Per comodità di visualizzazione in questo tutorial, guarda cosa succede quando esporti in PDF usando rmMkdwn.tplx.
!jupyter nbconvert --to pdf 'Example.ipynb' --template='rmMkdwn.tplx'
from IPython.display import IFrame
IFrame('Example.pdf', width=800, height=500)
[NbConvertApp] Converting notebook Example.ipynb to pdf
[NbConvertApp] Support files will be in Example_files/
[NbConvertApp] Making directory Example_files
[NbConvertApp] Writing 16047 bytes to notebook.tex
[NbConvertApp] Building PDF
[NbConvertApp] Running xelatex 3 times: ['xelatex', 'notebook.tex']
[NbConvertApp] Running bibtex 1 time: ['bibtex', 'notebook']
[NbConvertApp] WARNING | bibtex had problems, most likely because there were no citations
[NbConvertApp] PDF successfully created
[NbConvertApp] Writing 16102 bytes to Example.pdf

Nota che questo output è molto diverso dalla versione HTML. LaTeX inserisce la prima cella Markdown come titolo dell'articolo, quindi appare comunque nell'output. Il template ha rimosso correttamente il sottotitolo (quindi ha considerato quella cella Markdown come vero Markdown). La classe di documento article aggiorna la data a oggi, cosa che non è presente nel Notebook originale. Il font e la spaziatura sono diversi rispetto alla versione HTML. Infine, per impostazione predefinita l'output usa la visualizzazione classica di IPython, non la visualizzazione "Notebook style".
Se decidi di estendere una classe di documento LaTeX presente in Jupyter, assicurati di capire quale formattazione utilizzerà.
Ci sono alcuni punti chiave da ricordare su template, Jinja2 e nbconvert.
I template definiscono come un documento verrà visualizzato su una pagina web o in un altro formato di output. I Jupyter Notebook implementano template Jinja per visualizzare diversi formati di esportazione. I template hanno regole di ereditarietà che ti permettono di definire template genitori e figli per pagine simili, con formattazioni leggermente diverse.
I template Jinja hanno statements, expressions e (facoltativamente) comments. Le Statements, definite da {% statement %}, definiscono la struttura del template. Le Expressions, definite da {{ expression }}, riempiono il template con i tuoi dati. E i comments, definiti da {# comment #}, non vengono visualizzati nell'output: sono solo interni al template.
nbconvert è una libreria Python che ti permette di convertire il tuo Jupyter Notebook in altri formati, come HTML, LaTeX e PDF. nbconvert usa template Jinja per definire come i Jupyter Notebook verranno visualizzati in questi formati. Puoi definire template personalizzati o estendere i template predefiniti di Jupyter usando l'ereditarietà.
Ora sei pronto per iniziare a creare i tuoi template ed esportare bellissimi documenti Jupyter Notebook!
Riferimenti:
Scopri di più su Python
{count, plural, one {Corso} other {Corsi}}
{count, plural, one {Corso} other {Corsi}}
{count, plural, one {Corso} other {Corsi}}

{count, plural, one {blog} other {blogs}}
Abid Ali Awan
10 min
{count, plural, one {blog} other {blogs}}
Tim Lu
12 min

{count, plural, one {blog} other {blogs}}
Abid Ali Awan
15 min