The IPython Notebook is a browser-based interactive interface to Python. It was added to the IPython family in early 2012 and it has become quite popular since then. It has many great features that I won't be talking about here, but you can learn more on the IPython website.
The notebook is structured in cells each containing either text or code. Each cell containing code can be executed independently. However, the code in a cell might depend on imports or variables defined in a previous cell. Once a variable is defined it stays defined until the kernel is restarted. The behavior is mathematica or maple-like in that the result of a cell is displayed in the output section below the cell.
Notes, comments, code and results are all in one place. It is very easy to see the effect of changes and iterate to a solution. No need to switch between a text editor and the command line, everything happens within the Notebook. In my experience this is a particularly important feature.
The code cells act like miniature text editors. They provide syntax highlighting, automatic indentation, and tab completion.
Code documentation and autocompletion are available for all classes that have been loaded in memory at least once.
For example, we want to create a TH1F but we do not know the arguments to the constructor. By typing out TH1F(
and waiting a moment (or pressing tab) a floating help window will show the call signature and docstring. Pressing tab again will expand the window and make it scrollable. Typing TH1F?
will open a similar help string in a frame at the bottom of the Notebook window.
from ROOT import TH1F
h1 = TH1F( #"h1name", "title", 100, 0, 100)
TH1F?
Hit save or ctrl-s (cmd-s on mac) to save the notebook page. It will automatically save checkpoints at regular intervals without any need of action.
If connection is lost the changes will stay in the browser window. You only loose the ability to run code. After reconnecting you can save your latest changes and continue editing and running.
The Notebook internal format is json and it can be easily shared and version controlled. It is possible to export the notebook as a python script. All the non code text will appear in the script as comment strings.
The IPython developers provide a service called nbviewer that renders Notebooks posted on the web. It has become extremely common to share demonstrations of Python topics by making a Notebook, posting it in a repo or gist, and sharing a link to the rendered Notebook on nbviewer.
Notebook cells support several formats: six levels of headings, raw text, Markdown (supporting also Latex), and code. Programming examples can be accompanied by richly formatted explanations and links to other resources. It's also possible to embed images and videos, both local and via YouTube.
This is an example of a markdown cell including LATEX, such as Z→μ+μ−. Double click on a text cell to edit its content.
A little bonus showing how to draw a progress bar. It is not recommended when connecting to a remote server on the other side of the ocean since the time spent waiting for data packages to arrive to update the bar will make this a bottleneck.
from ProgressBar import ProgressBar
import time
p = ProgressBar(1000)
for i in range(1001):
time.sleep(0.002)
p.animate(i)
[*********************100%***********************] 1000 of 1000 complete
print open("ProgressBar.py").read()
from __future__ import print_function import sys, time class ProgressBar: def __init__(self, iterations): self.iterations = iterations self.prog_bar = '[]' self.fill_char = '*' self.width = 50 self.__update_amount(0) def animate(self, iter): print('\r', self, end='') sys.stdout.flush() self.update_iteration(iter + 1) def update_iteration(self, elapsed_iter): self.__update_amount((elapsed_iter / float(self.iterations)) * 100.0) self.prog_bar += ' %d of %s complete' % (elapsed_iter, self.iterations) if elapsed_iter == self.iterations: self.prog_bar += '\n\n' def __update_amount(self, new_amount): percent_done = int(round((new_amount / 100.0) * 100.0)) all_full = self.width - 2 num_hashes = int(round((percent_done / 100.0) * all_full)) self.prog_bar = '[' + self.fill_char * num_hashes + ' ' * (all_full - num_hashes) + ']' pct_place = (len(self.prog_bar) // 2) - len(str(percent_done)) pct_string = '%d%%' % percent_done self.prog_bar = self.prog_bar[0:pct_place] + \ (pct_string + self.prog_bar[pct_place + len(pct_string):]) def __str__(self): return str(self.prog_bar)