Skip to article frontmatterSkip to article content

IPython: beyond plain Python

Updated by @espg from the 2019 ICESat2 Hackweek intro-jupyter-git session, written by @fperez.

When executing code in IPython, all valid Python syntax works as-is, but IPython provides a number of features designed to make the interactive experience more fluid and efficient.

First things first: running code, getting help

In the notebook, to run a cell of code, hit Shift-Enter. This executes the cell and puts the cursor in the next cell below, or makes a new one if you are at the end. Alternately, you can use:

  • Alt-Enter to force the creation of a new cell unconditionally (useful when inserting new content in the middle of an existing notebook).

  • Control-Enter executes the cell and keeps the cursor in the same cell, useful for quick experimentation of snippets that you don’t need to keep permanently.

print("Hi")
Hi

Getting help:

?
IPython -- An enhanced Interactive Python ========================================= IPython offers a fully compatible replacement for the standard Python interpreter, with convenient shell features, special commands, command history mechanism and output results caching. At your system command line, type 'ipython -h' to see the command line options available. This document only describes interactive features. GETTING HELP ------------ Within IPython you have various way to access help: ? -> Introduction and overview of IPython's features (this screen). object? -> Details about 'object'. object?? -> More detailed, verbose information about 'object'. %quickref -> Quick reference of all IPython specific syntax and magics. help -> Access Python's own help system. If you are in terminal IPython you can quit this screen by pressing `q`. MAIN FEATURES ------------- * Access to the standard Python help with object docstrings and the Python manuals. Simply type 'help' (no quotes) to invoke it. * Magic commands: type %magic for information on the magic subsystem. * System command aliases, via the %alias command or the configuration file(s). * Dynamic object information: Typing ?word or word? prints detailed information about an object. Certain long strings (code, etc.) get snipped in the center for brevity. Typing ??word or word?? gives access to the full information without snipping long strings. Strings that are longer than the screen are printed through the less pager. The ?/?? system gives access to the full source code for any object (if available), shows function prototypes and other useful information. If you just want to see an object's docstring, type '%pdoc object' (without quotes, and without % if you have automagic on). * Tab completion in the local namespace: At any time, hitting tab will complete any available python commands or variable names, and show you a list of the possible completions if there's no unambiguous one. It will also complete filenames in the current directory. * Search previous command history in multiple ways: - Start typing, and then use arrow keys up/down or (Ctrl-p/Ctrl-n) to search through the history items that match what you've typed so far. - Hit Ctrl-r: opens a search prompt. Begin typing and the system searches your history for lines that match what you've typed so far, completing as much as it can. - %hist: search history by index. * Persistent command history across sessions. * Logging of input with the ability to save and restore a working session. * System shell with !. Typing !ls will run 'ls' in the current directory. * The reload command does a 'deep' reload of a module: changes made to the module since you imported will actually be available without having to exit. * Verbose and colored exception traceback printouts. See the magic xmode and xcolor functions for details (just type %magic). * Input caching system: IPython offers numbered prompts (In/Out) with input and output caching. All input is saved and can be retrieved as variables (besides the usual arrow key recall). The following GLOBAL variables always exist (so don't overwrite them!): _i: stores previous input. _ii: next previous. _iii: next-next previous. _ih : a list of all input _ih[n] is the input from line n. Additionally, global variables named _i<n> are dynamically created (<n> being the prompt counter), such that _i<n> == _ih[<n>] For example, what you typed at prompt 14 is available as _i14 and _ih[14]. You can create macros which contain multiple input lines from this history, for later re-execution, with the %macro function. The history function %hist allows you to see any part of your input history by printing a range of the _i variables. Note that inputs which contain magic functions (%) appear in the history with a prepended comment. This is because they aren't really valid Python code, so you can't exec them. * Output caching system: For output that is returned from actions, a system similar to the input cache exists but using _ instead of _i. Only actions that produce a result (NOT assignments, for example) are cached. If you are familiar with Mathematica, IPython's _ variables behave exactly like Mathematica's % variables. The following GLOBAL variables always exist (so don't overwrite them!): _ (one underscore): previous output. __ (two underscores): next previous. ___ (three underscores): next-next previous. Global variables named _<n> are dynamically created (<n> being the prompt counter), such that the result of output <n> is always available as _<n>. Finally, a global dictionary named _oh exists with entries for all lines which generated output. * Directory history: Your history of visited directories is kept in the global list _dh, and the magic %cd command can be used to go to any entry in that list. * Auto-parentheses and auto-quotes (adapted from Nathan Gray's LazyPython) 1. Auto-parentheses Callable objects (i.e. functions, methods, etc) can be invoked like this (notice the commas between the arguments):: In [1]: callable_ob arg1, arg2, arg3 and the input will be translated to this:: callable_ob(arg1, arg2, arg3) This feature is off by default (in rare cases it can produce undesirable side-effects), but you can activate it at the command-line by starting IPython with `--autocall 1`, set it permanently in your configuration file, or turn on at runtime with `%autocall 1`. You can force auto-parentheses by using '/' as the first character of a line. For example:: In [1]: /globals # becomes 'globals()' Note that the '/' MUST be the first character on the line! This won't work:: In [2]: print /globals # syntax error In most cases the automatic algorithm should work, so you should rarely need to explicitly invoke /. One notable exception is if you are trying to call a function with a list of tuples as arguments (the parenthesis will confuse IPython):: In [1]: zip (1,2,3),(4,5,6) # won't work but this will work:: In [2]: /zip (1,2,3),(4,5,6) ------> zip ((1,2,3),(4,5,6)) Out[2]= [(1, 4), (2, 5), (3, 6)] IPython tells you that it has altered your command line by displaying the new command line preceded by -->. e.g.:: In [18]: callable list -------> callable (list) 2. Auto-Quoting You can force auto-quoting of a function's arguments by using ',' as the first character of a line. For example:: In [1]: ,my_function /home/me # becomes my_function("/home/me") If you use ';' instead, the whole argument is quoted as a single string (while ',' splits on whitespace):: In [2]: ,my_function a b c # becomes my_function("a","b","c") In [3]: ;my_function a b c # becomes my_function("a b c") Note that the ',' MUST be the first character on the line! This won't work:: In [4]: x = ,my_function /home/me # syntax error

Typing object_name? will print all sorts of details about any object, including docstrings, function definition lines (for call arguments) and constructor details for classes.

import numpy as np
np.linspace?
Signature: np.linspace( start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0, *, device=None, ) Call signature: np.linspace(*args, **kwargs) Type: _ArrayFunctionDispatcher String form: <function linspace at 0x7a74fc125ee0> File: /srv/conda/envs/notebook/lib/python3.12/site-packages/numpy/_core/function_base.py Docstring: Return evenly spaced numbers over a specified interval. Returns `num` evenly spaced samples, calculated over the interval [`start`, `stop`]. The endpoint of the interval can optionally be excluded. .. versionchanged:: 1.20.0 Values are rounded towards ``-inf`` instead of ``0`` when an integer ``dtype`` is specified. The old behavior can still be obtained with ``np.linspace(start, stop, num).astype(int)`` Parameters ---------- start : array_like The starting value of the sequence. stop : array_like The end value of the sequence, unless `endpoint` is set to False. In that case, the sequence consists of all but the last of ``num + 1`` evenly spaced samples, so that `stop` is excluded. Note that the step size changes when `endpoint` is False. num : int, optional Number of samples to generate. Default is 50. Must be non-negative. endpoint : bool, optional If True, `stop` is the last sample. Otherwise, it is not included. Default is True. retstep : bool, optional If True, return (`samples`, `step`), where `step` is the spacing between samples. dtype : dtype, optional The type of the output array. If `dtype` is not given, the data type is inferred from `start` and `stop`. The inferred dtype will never be an integer; `float` is chosen even if the arguments would produce an array of integers. axis : int, optional The axis in the result to store the samples. Relevant only if start or stop are array-like. By default (0), the samples will be along a new axis inserted at the beginning. Use -1 to get an axis at the end. device : str, optional The device on which to place the created array. Default: None. For Array-API interoperability only, so must be ``"cpu"`` if passed. .. versionadded:: 2.0.0 Returns ------- samples : ndarray There are `num` equally spaced samples in the closed interval ``[start, stop]`` or the half-open interval ``[start, stop)`` (depending on whether `endpoint` is True or False). step : float, optional Only returned if `retstep` is True Size of spacing between samples. See Also -------- arange : Similar to `linspace`, but uses a step size (instead of the number of samples). geomspace : Similar to `linspace`, but with numbers spaced evenly on a log scale (a geometric progression). logspace : Similar to `geomspace`, but with the end points specified as logarithms. :ref:`how-to-partition` Examples -------- >>> import numpy as np >>> np.linspace(2.0, 3.0, num=5) array([2. , 2.25, 2.5 , 2.75, 3. ]) >>> np.linspace(2.0, 3.0, num=5, endpoint=False) array([2. , 2.2, 2.4, 2.6, 2.8]) >>> np.linspace(2.0, 3.0, num=5, retstep=True) (array([2. , 2.25, 2.5 , 2.75, 3. ]), 0.25) Graphical illustration: >>> import matplotlib.pyplot as plt >>> N = 8 >>> y = np.zeros(N) >>> x1 = np.linspace(0, 10, N, endpoint=True) >>> x2 = np.linspace(0, 10, N, endpoint=False) >>> plt.plot(x1, y, 'o') [<matplotlib.lines.Line2D object at 0x...>] >>> plt.plot(x2, y + 0.5, 'o') [<matplotlib.lines.Line2D object at 0x...>] >>> plt.ylim([-0.5, 1]) (-0.5, 1) >>> plt.show() Class docstring: Class to wrap functions with checks for __array_function__ overrides. All arguments are required, and can only be passed by position. Parameters ---------- dispatcher : function or None The dispatcher function that returns a single sequence-like object of all arguments relevant. It must have the same signature (except the default values) as the actual implementation. If ``None``, this is a ``like=`` dispatcher and the ``_ArrayFunctionDispatcher`` must be called with ``like`` as the first (additional and positional) argument. implementation : function Function that implements the operation on NumPy arrays without overrides. Arguments passed calling the ``_ArrayFunctionDispatcher`` will be forwarded to this (and the ``dispatcher``) as if using ``*args, **kwargs``. Attributes ---------- _implementation : function The original implementation passed in.
np.isclose??
Signature: np.isclose(a, b, rtol=1e-05, atol=1e-08, equal_nan=False) Call signature: np.isclose(*args, **kwargs) Type: _ArrayFunctionDispatcher String form: <function isclose at 0x7a74fc105260> File: /srv/conda/envs/notebook/lib/python3.12/site-packages/numpy/_core/numeric.py Source: @array_function_dispatch(_isclose_dispatcher) def isclose(a, b, rtol=1.e-5, atol=1.e-8, equal_nan=False): """ Returns a boolean array where two arrays are element-wise equal within a tolerance. The tolerance values are positive, typically very small numbers. The relative difference (`rtol` * abs(`b`)) and the absolute difference `atol` are added together to compare against the absolute difference between `a` and `b`. .. warning:: The default `atol` is not appropriate for comparing numbers with magnitudes much smaller than one (see Notes). Parameters ---------- a, b : array_like Input arrays to compare. rtol : array_like The relative tolerance parameter (see Notes). atol : array_like The absolute tolerance parameter (see Notes). equal_nan : bool Whether to compare NaN's as equal. If True, NaN's in `a` will be considered equal to NaN's in `b` in the output array. Returns ------- y : array_like Returns a boolean array of where `a` and `b` are equal within the given tolerance. If both `a` and `b` are scalars, returns a single boolean value. See Also -------- allclose math.isclose Notes ----- For finite values, isclose uses the following equation to test whether two floating point values are equivalent.:: absolute(a - b) <= (atol + rtol * absolute(b)) Unlike the built-in `math.isclose`, the above equation is not symmetric in `a` and `b` -- it assumes `b` is the reference value -- so that `isclose(a, b)` might be different from `isclose(b, a)`. The default value of `atol` is not appropriate when the reference value `b` has magnitude smaller than one. For example, it is unlikely that ``a = 1e-9`` and ``b = 2e-9`` should be considered "close", yet ``isclose(1e-9, 2e-9)`` is ``True`` with default settings. Be sure to select `atol` for the use case at hand, especially for defining the threshold below which a non-zero value in `a` will be considered "close" to a very small or zero value in `b`. `isclose` is not defined for non-numeric data types. :class:`bool` is considered a numeric data-type for this purpose. Examples -------- >>> import numpy as np >>> np.isclose([1e10,1e-7], [1.00001e10,1e-8]) array([ True, False]) >>> np.isclose([1e10,1e-8], [1.00001e10,1e-9]) array([ True, True]) >>> np.isclose([1e10,1e-8], [1.0001e10,1e-9]) array([False, True]) >>> np.isclose([1.0, np.nan], [1.0, np.nan]) array([ True, False]) >>> np.isclose([1.0, np.nan], [1.0, np.nan], equal_nan=True) array([ True, True]) >>> np.isclose([1e-8, 1e-7], [0.0, 0.0]) array([ True, False]) >>> np.isclose([1e-100, 1e-7], [0.0, 0.0], atol=0.0) array([False, False]) >>> np.isclose([1e-10, 1e-10], [1e-20, 0.0]) array([ True, True]) >>> np.isclose([1e-10, 1e-10], [1e-20, 0.999999e-10], atol=0.0) array([False, True]) """ # Turn all but python scalars into arrays. x, y, atol, rtol = ( a if isinstance(a, (int, float, complex)) else asanyarray(a) for a in (a, b, atol, rtol)) # Make sure y is an inexact type to avoid bad behavior on abs(MIN_INT). # This will cause casting of x later. Also, make sure to allow subclasses # (e.g., for numpy.ma). # NOTE: We explicitly allow timedelta, which used to work. This could # possibly be deprecated. See also gh-18286. # timedelta works if `atol` is an integer or also a timedelta. # Although, the default tolerances are unlikely to be useful if (dtype := getattr(y, "dtype", None)) is not None and dtype.kind != "m": dt = multiarray.result_type(y, 1.) y = asanyarray(y, dtype=dt) elif isinstance(y, int): y = float(y) with errstate(invalid='ignore'): result = (less_equal(abs(x-y), atol + rtol * abs(y)) & isfinite(y) | (x == y)) if equal_nan: result |= isnan(x) & isnan(y) return result[()] # Flatten 0d arrays to scalars Class docstring: Class to wrap functions with checks for __array_function__ overrides. All arguments are required, and can only be passed by position. Parameters ---------- dispatcher : function or None The dispatcher function that returns a single sequence-like object of all arguments relevant. It must have the same signature (except the default values) as the actual implementation. If ``None``, this is a ``like=`` dispatcher and the ``_ArrayFunctionDispatcher`` must be called with ``like`` as the first (additional and positional) argument. implementation : function Function that implements the operation on NumPy arrays without overrides. Arguments passed calling the ``_ArrayFunctionDispatcher`` will be forwarded to this (and the ``dispatcher``) as if using ``*args, **kwargs``. Attributes ---------- _implementation : function The original implementation passed in.
*int*?
FloatingPointError breakpoint int print

An IPython quick reference card:

%quickref
IPython -- An enhanced Interactive Python - Quick Reference Card ================================================================ obj?, obj?? : Get help, or more help for object (also works as ?obj, ??obj). ?foo.*abc* : List names in 'foo' containing 'abc' in them. %magic : Information about IPython's 'magic' % functions. Magic functions are prefixed by % or %%, and typically take their arguments without parentheses, quotes or even commas for convenience. Line magics take a single % and cell magics are prefixed with two %%. Example magic function calls: %alias d ls -F : 'd' is now an alias for 'ls -F' alias d ls -F : Works if 'alias' not a python name alist = %alias : Get list of aliases to 'alist' cd /usr/share : Obvious. cd -<tab> to choose from visited dirs. %cd?? : See help AND source for magic %cd %timeit x=10 : time the 'x=10' statement with high precision. %%timeit x=2**100 x**100 : time 'x**100' with a setup of 'x=2**100'; setup code is not counted. This is an example of a cell magic. System commands: !cp a.txt b/ : System command escape, calls os.system() cp a.txt b/ : after %rehashx, most system commands work without ! cp ${f}.txt $bar : Variable expansion in magics and system commands files = !ls /usr : Capture system command output files.s, files.l, files.n: "a b c", ['a','b','c'], 'a\nb\nc' History: _i, _ii, _iii : Previous, next previous, next next previous input _i4, _ih[2:5] : Input history line 4, lines 2-4 exec(_i81) : Execute input history line #81 again %rep 81 : Edit input history line #81 _, __, ___ : previous, next previous, next next previous output _dh : Directory history _oh : Output history %hist : Command history of current session. %hist -g foo : Search command history of (almost) all sessions for 'foo'. %hist -g : Command history of (almost) all sessions. %hist 1/2-8 : Command history containing lines 2-8 of session 1. %hist 1/ ~2/ : Command history of session 1 and 2 sessions before current. %hist ~8/1-~6/5 : Command history from line 1 of 8 sessions ago to line 5 of 6 sessions ago. %edit 0/ : Open editor to execute code with history of current session. Autocall: f 1,2 : f(1,2) # Off by default, enable with %autocall magic. /f 1,2 : f(1,2) (forced autoparen) ,f 1 2 : f("1","2") ;f 1 2 : f("1 2") Remember: TAB completion works in many contexts, not just file names or python names. The following magic functions are currently available: %alias: Define an alias for a system command. %alias_magic: :: %autoawait: %autocall: Make functions callable without having to type parentheses. %automagic: Make magic functions callable without having to type the initial %. %autosave: Set the autosave interval in the notebook (in seconds). %bookmark: Manage IPython's bookmark system. %cat: Alias for `!cat` %cd: Change the current working directory. %clear: Clear the terminal. %code_wrap: :: %colors: Switch color scheme/theme globally for IPython %conda: Run the conda package manager within the current kernel. %config: configure IPython %connect_info: Print information for connecting other clients to this kernel %cp: Alias for `!cp` %debug: :: %dhist: Print your history of visited directories. %dirs: Return the current directory stack. %doctest_mode: Toggle doctest mode on and off. %ed: Alias for `%edit`. %edit: Bring up an editor and execute the resulting code. %env: Get, set, or list environment variables. %gui: Enable or disable IPython GUI event loop integration. %hist: Alias for `%history`. %history: :: %killbgscripts: Kill all BG processes started by %%script and its family. %ldir: Alias for `!ls -F -o --color %l | grep /$` %less: Show a file through the pager. %lf: Alias for `!ls -F -o --color %l | grep ^-` %lk: Alias for `!ls -F -o --color %l | grep ^l` %ll: Alias for `!ls -F -o --color` %load: Load code into the current frontend. %load_ext: Load an IPython extension by its module name. %loadpy: Alias of `%load` %logoff: Temporarily stop logging. %logon: Restart logging. %logstart: Start logging anywhere in a session. %logstate: Print the status of the logging system. %logstop: Fully stop logging and close log file. %ls: Alias for `!ls -F --color` %lsmagic: List currently available magic functions. %lx: Alias for `!ls -F -o --color %l | grep ^-..x` %macro: Define a macro for future re-execution. It accepts ranges of history, %magic: Print information about the magic function system. %mamba: Run the mamba package manager within the current kernel. %man: Find the man page for the given command and display in pager. %matplotlib: :: %micromamba: Run the conda package manager within the current kernel. %mkdir: Alias for `!mkdir` %more: Show a file through the pager. %mv: Alias for `!mv` %notebook: :: %page: Pretty print the object and display it through a pager. %pastebin: Upload code to dpaste.com, returning the URL. %pdb: Control the automatic calling of the pdb interactive debugger. %pdef: Print the call signature for any callable object. %pdoc: Print the docstring for an object. %pfile: Print (or run through pager) the file where an object is defined. %pinfo: Provide detailed information about an object. %pinfo2: Provide extra detailed information about an object. %pip: Run the pip package manager within the current kernel. %popd: Change to directory popped off the top of the stack. %pprint: Toggle pretty printing on/off. %precision: Set floating point precision for pretty printing. %prun: Run a statement through the python code profiler. %psearch: Search for object in namespaces by wildcard. %psource: Print (or run through pager) the source code for an object. %pushd: Place the current dir on stack and change directory. %pwd: Return the current working directory path. %pycat: Show a syntax-highlighted file through a pager. %pylab: :: %qtconsole: Open a qtconsole connected to this kernel. %quickref: Show a quick reference sheet %recall: Repeat a command, or get command to input line for editing. %rehashx: Update the alias table with all executable files in $PATH. %reload_ext: Reload an IPython extension by its module name. %rep: Alias for `%recall`. %rerun: Re-run previous input %reset: Resets the namespace by removing all names defined by the user, if %reset_selective: Resets the namespace by removing names defined by the user. %rm: Alias for `!rm` %rmdir: Alias for `!rmdir` %run: Run the named file inside IPython as a program. %save: Save a set of lines or a macro to a given filename. %sc: Shell capture - run shell command and capture output (DEPRECATED use !). %set_env: Set environment variables. Assumptions are that either "val" is a %store: Lightweight persistence for python variables. %sx: Shell execute - run shell command and capture output (!! is short-hand). %system: Shell execute - run shell command and capture output (!! is short-hand). %tb: Print the last traceback. %time: Time execution of a Python statement or expression. %timeit: Time execution of a Python statement or expression %unalias: Remove an alias %unload_ext: Unload an IPython extension by its module name. %uv: Run the uv package manager within the current kernel. %who: Print all interactive variables, with some minimal formatting. %who_ls: Return a sorted list of all interactive variables. %whos: Like %who, but gives some extra information about each variable. %xdel: Delete a variable, trying to clear it from anywhere that %xmode: Switch modes for the exception handlers. %%!: Shell execute - run shell command and capture output (!! is short-hand). %%HTML: Alias for `%%html`. %%SVG: Alias for `%%svg`. %%bash: %%bash script magic %%capture: :: %%code_wrap: :: %%debug: :: %%file: Alias for `%%writefile`. %%html: :: %%javascript: Run the cell block of Javascript code %%js: Run the cell block of Javascript code %%latex: Render the cell as a block of LaTeX %%markdown: Render the cell as Markdown text block %%perl: %%perl script magic %%prun: Run a statement through the python code profiler. %%pypy: %%pypy script magic %%python: %%python script magic %%python2: %%python2 script magic %%python3: %%python3 script magic %%ruby: %%ruby script magic %%script: :: %%sh: %%sh script magic %%svg: Render the cell as an SVG literal %%sx: Shell execute - run shell command and capture output (!! is short-hand). %%system: Shell execute - run shell command and capture output (!! is short-hand). %%time: Time execution of a Python statement or expression. %%timeit: Time execution of a Python statement or expression %%writefile: ::

Tab completion

Tab completion, especially for attributes, is a convenient way to explore the structure of any object you’re dealing with. Simply type object_name.<TAB> to view the object’s attributes. Besides Python objects and keywords, tab completion also works on file and directory names.

import numpy as np
np.abs

Tab completion also works for accessing documentation. Using Shift-TAB after the parens will display the function or class signature:

np.zeros(10, dt
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float16)

You can suppress the storage and rendering of output if you append ; to the last cell (this comes in handy when plotting with matplotlib, for example):

10+20;

Accessing the underlying operating system

You can invoke the command line from within the notebook by prepending the “bang” ( ! ) operator:

!pwd
/home/jovyan/site/lectures/intro-jupyter

Some of the most common shell commands will work without prepending:

ls
01-Intro-Jupyter.ipynb         04-Rich-Output.ipynb       Index.ipynb
02-Beyond-Plain-Python.ipynb   05-widgets-interact.ipynb
03-Custom-Display-Logic.ipynb  images/
pwd
'/home/jovyan/site/lectures/intro-jupyter'

...but others require the bang operator:

du
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[12], line 1
----> 1 du

NameError: name 'du' is not defined
!du
180	./.ipynb_checkpoints
764	./images
1540	.

It’s best practice to use the operator in all cases, since it makes it more explicit when you are calling the shell

files = !ls 
print("files this directory:")
print(files)
files this directory:
['01-Intro-Jupyter.ipynb', '02-Beyond-Plain-Python.ipynb', '03-Custom-Display-Logic.ipynb', '04-Rich-Output.ipynb', '05-widgets-interact.ipynb', 'images', 'Index.ipynb']
files
['01-Intro-Jupyter.ipynb', '02-Beyond-Plain-Python.ipynb', '03-Custom-Display-Logic.ipynb', '04-Rich-Output.ipynb', '05-widgets-interact.ipynb', 'images', 'Index.ipynb']
!echo $files
[01-Intro-Jupyter.ipynb, 02-Beyond-Plain-Python.ipynb, 03-Custom-Display-Logic.ipynb, 04-Rich-Output.ipynb, 05-widgets-interact.ipynb, images, Index.ipynb]
!echo {files[0].upper()}
01-INTRO-JUPYTER.IPYNB

Note that all this is available even in multiline blocks:

import os
for i,f in enumerate(files):
    if f.endswith('ipynb'):
        !echo {"%02d" % i} - "{os.path.splitext(f)[0]}"
    else:
        print('--')
00 - 01-Intro-Jupyter
01 - 02-Beyond-Plain-Python
02 - 03-Custom-Display-Logic
03 - 04-Rich-Output
04 - 05-widgets-interact
--
06 - Index

Beyond Python: magic functions

The IPython ‘magic’ functions are a set of commands, invoked by prepending one or two % signs to their name, that live in a namespace separate from your normal Python variables and provide a more command-like interface. They take flags with -- and arguments without quotes, parentheses or commas. The motivation behind this system is two-fold:

  • To provide an namespace for controlling IPython itself and exposing other system-oriented functionality that is separate from your Python variables and functions. This lets you have a cd command accessible as a magic regardless of whether you have a Python cd variable.

  • To expose a calling mode that requires minimal verbosity and typing while working interactively. Thus the inspiration taken from the classic Unix shell style for commands.

%magic

Line vs cell magics:

Magics can be applied at the single-line level or to entire cells. Line magics are identified with a single % prefix, while cell magics use %% and can only be used as the first line of the cell (since they apply to the entire cell). Some magics, like the convenient %timeit that ships built-in with IPython, can be called in either mode, while others may be line- or cell-only (you can see all magics with %lsmagic).

Let’s see this with some %timeit examples:

%timeit list(range(1000))
%%timeit
# comment here

list(range(10))
list(range(100))

Line magics can be used even inside code blocks:

for i in range(1, 5):
    size = i*100
    print('size:', size, end=' ')
    %timeit list(range(size))

Magics can do anything they want with their input, so it doesn’t have to be valid Python (note that the below may not work on a Windows machine, depending on how you are running Jupyter on it):

%%bash
echo "My shell is:" $SHELL
echo "My disk usage is:"
df -h

Another interesting cell magic: create any file you want locally from the notebook:

%%writefile test.txt
This is a test file.
It can contain anything I want...

And more...
!cat test.txt

Let’s see what other magics are currently defined in the system:

%lsmagic

Plotting in the notebook

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 2*np.pi, 300)
y = np.sin(x**2)
plt.plot(x, y)
plt.title("A little chirp");
<Figure size 640x480 with 1 Axes>

Running normal Python code: execution and errors

Not only can you input normal Python code, you can even paste straight from a Python or IPython shell session:

>>> # Fibonacci series:
... # the sum of two elements defines the next
... a, b = 0, 1
>>> while b < 10:
...     print(b)
...     a, b = b, a+b
1
1
2
3
5
8
In [1]: for i in range(10):
   ...:     print(i, end=' ')
   ...:     
0 1 2 3 4 5 6 7 8 9 

And when your code produces errors, you can control how they are displayed with the %xmode magic:

%%writefile mod.py

def f(x):
    return 1.0/(x-1)

def g(y):
    return f(y+1)
Writing mod.py

Now let’s call the function g with an argument that would produce an error:

import mod
mod.g(0)
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
Input In [26], in <module>
      1 import mod
----> 2 mod.g(0)

File ~/teach/stat159/2022sp/site/lectures/intro-jupyter/mod.py:6, in g(y)
      5 def g(y):
----> 6     return f(y+1)

File ~/teach/stat159/2022sp/site/lectures/intro-jupyter/mod.py:3, in f(x)
      2 def f(x):
----> 3     return 1.0/(x-1)

ZeroDivisionError: float division by zero

Basic debugging

When running code interactively, it can be tricky to figure out how to debug...

%debug
> /Users/fperez/teach/stat159/2022sp/site/lectures/intro-jupyter/mod.py(3)f()
      1 
      2 def f(x):
----> 3     return 1.0/(x-1)
      4 
      5 def g(y):

ipdb>  q
enjoy = input('Are you enjoying this tutorial? ')
print('enjoy is:', enjoy)
Are you enjoying this tutorial?  q
enjoy is: q

Running code in other languages with special %% magics

%%perl
@months = ("July", "August", "September");
print $months[0];
July