{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "> This is one of the 100 recipes of the [IPython Cookbook](http://ipython-books.github.io/), the definitive guide to high-performance scientific computing and data science in Python.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 1.4. Creating an IPython extension with custom magic commands" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Let's import a few functions from the IPython magic system." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from IPython.core.magic import (register_line_magic, \n", " register_cell_magic)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "2. Defining a new line magic is particularly simple. First, let's create a function that accepts the contents of the line (except the initial `%`-prefixed magic command). The name of this function is the name of the magic. Then, let's decorate this function with `@register_line_magic`. We're done!" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "@register_line_magic\n", "def hello(line):\n", " if line == 'french':\n", " print(\"Salut tout le monde!\")\n", " else:\n", " print(\"Hello world!\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%hello" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%hello french" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "3. Let's create a slightly more useful cell magic `%%csv` that parses a CSV string and returns a Pandas DataFrame object. This time, the function takes as argument the first line (what follows `%%csv`), and the contents of the cell (everything in the cell except the first line)." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import pandas as pd\n", "#from StringIO import StringIO # Python 2\n", "from io import StringIO # Python 3\n", "\n", "@register_cell_magic\n", "def csv(line, cell):\n", " # We create a string buffer containing the\n", " # contents of the cell.\n", " sio = StringIO(cell)\n", " # We use Pandas' read_csv function to parse\n", " # the CSV string.\n", " return pd.read_csv(sio)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%csv\n", "col1,col2,col3\n", "0,1,2\n", "3,4,5\n", "7,8,9" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can access the returned object with `_`." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "df = _\n", "df.describe()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "4. The method we described is useful in an interactive session. If you want to use the same magic in multiple notebooks, or if you want to distribute it, you need to create an **IPython extension** that implements your custom magic command. Let's show how to do that. The first step is to create a Python script (`csvmagic.py` here) that implements the magic." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%writefile csvmagic.py\n", "import pandas as pd\n", "#from StringIO import StringIO # Python 2\n", "from io import StringIO # Python 3\n", "\n", "def csv(line, cell):\n", " sio = StringIO(cell)\n", " return pd.read_csv(sio)\n", "\n", "def load_ipython_extension(ipython):\n", " \"\"\"This function is called when the extension is loaded.\n", " It accepts an IPython InteractiveShell instance.\n", " We can register the magic with the `register_magic_function`\n", " method of the shell instance.\"\"\"\n", " ipython.register_magic_function(csv, 'cell')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "5. Once the extension is created, we need to import it in the IPython session. The `%load_ext` magic command takes the name of a Python module and imports it, calling immediately `load_ipython_extension`. Here, loading this extension automatically registers our magic function `%%csv`. The Python module needs to be importable. Here, it is in the current directory. In other situations, it has to be in the Python path. It can also be stored in `~\\.ipython\\extensions` which is automatically put in the Python path." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%load_ext csvmagic" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%csv\n", "col1,col2,col3\n", "0,1,2\n", "3,4,5\n", "7,8,9" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, to ensure that this magic is automatically defined in our IPython profile, we can instruct IPython to load this extension at startup. To do this, let's open the file `~/.ipython/profile_default/ipython_config.py` and let's put `'csvmagic'` in the `c.InteractiveShellApp.extensions` list. The `csvmagic` module needs to be importable. It is common to create a *Python package* implementing an IPython extension, which itself defines custom magic commands." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> You'll find all the explanations, figures, references, and much more in the book (to be released later this summer).\n", "\n", "> [IPython Cookbook](http://ipython-books.github.io/), by [Cyrille Rossant](http://cyrille.rossant.net), Packt Publishing, 2014 (500 pages)." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.4.2" } }, "nbformat": 4, "nbformat_minor": 0 }