{ "metadata": { "name": "Script Magics" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "heading", "level": 1, "metadata": {}, "source": [ "Running Scripts from IPython" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "IPython has a `%%script` cell magic, which lets you run a cell in\n", "a subprocess of any interpreter on your system, such as: bash, ruby, perl, zsh, R, etc.\n", "\n", "It can even be a script of your own, which expects input on stdin." ] }, { "cell_type": "code", "collapsed": false, "input": [ "import sys" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 1 }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Basic usage" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To use it, simply pass a path or shell command to the program you want to run on the `%%script` line,\n", "and the rest of the cell will be run by that script, and stdout/err from the subprocess are captured and displayed." ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%script python\n", "import sys\n", "print 'hello from Python %s' % sys.version" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "hello from Python 2.7.1 (r271:86832, Jul 31 2011, 19:30:53) \n", "[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)]\n" ] } ], "prompt_number": 2 }, { "cell_type": "code", "collapsed": false, "input": [ "%%script python3\n", "import sys\n", "print('hello from Python: %s' % sys.version)" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "hello from Python: 3.2.3 (v3.2.3:3d0686d90f55, Apr 10 2012, 11:25:50) \n", "[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]\n" ] } ], "prompt_number": 3 }, { "cell_type": "markdown", "metadata": {}, "source": [ "IPython also creates aliases for a few common interpreters, such as bash, ruby, perl, etc.\n", "\n", "These are all equivalent to `%%script `" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%ruby\n", "puts \"Hello from Ruby #{RUBY_VERSION}\"" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Hello from Ruby 1.8.7\n" ] } ], "prompt_number": 4 }, { "cell_type": "code", "collapsed": false, "input": [ "%%bash\n", "echo \"hello from $BASH\"" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "hello from /usr/local/bin/bash\n" ] } ], "prompt_number": 5 }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Capturing output" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also capture stdout/err from these subprocesses into Python variables, instead of letting them go directly to stdout/err" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%bash\n", "echo \"hi, stdout\"\n", "echo \"hello, stderr\" >&2\n" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "hi, stdout\n" ] }, { "output_type": "stream", "stream": "stderr", "text": [ "hello, stderr\n" ] } ], "prompt_number": 6 }, { "cell_type": "code", "collapsed": false, "input": [ "%%bash --out output --err error\n", "echo \"hi, stdout\"\n", "echo \"hello, stderr\" >&2" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 7 }, { "cell_type": "code", "collapsed": false, "input": [ "print(error)\n", "print(output)" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "hello, stderr\n", "\n", "hi, stdout\n", "\n" ] } ], "prompt_number": 8 }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Background Scripts" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "These scripts can be run in the background, by adding the `--bg` flag.\n", "\n", "When you do this, output is discarded unless you use the `--out/err`\n", "flags to store output as above." ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%ruby --bg --out ruby_lines\n", "for n in 1...10\n", " sleep 1\n", " puts \"line #{n}\"\n", " STDOUT.flush\n", "end" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Starting job # 0 in a separate thread.\n" ] } ], "prompt_number": 9 }, { "cell_type": "markdown", "metadata": {}, "source": [ "When you do store output of a background thread, these are the stdout/err *pipes*,\n", "rather than the text of the output." ] }, { "cell_type": "code", "collapsed": false, "input": [ "ruby_lines" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "pyout", "prompt_number": 10, "text": [ "', mode 'rb' at 0x10a4be660>" ] } ], "prompt_number": 10 }, { "cell_type": "code", "collapsed": false, "input": [ "print(ruby_lines.read())" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "line 1\n", "line 2\n", "line 3\n", "line 4\n", "line 5\n", "line 6\n", "line 7\n", "line 8\n", "line 9\n", "\n" ] } ], "prompt_number": 11 }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Arguments to subcommand" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can pass arguments the subcommand as well,\n", "such as this example instructing Python to use integer division from Python 3:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%script python -Qnew\n", "print 1/3" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "0.333333333333\n" ] } ], "prompt_number": 12 }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can really specify *any* program for `%%script`,\n", "for instance here is a 'program' that echos the lines of stdin, with delays between each line." ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%script --bg --out bashout bash -c \"while read line; do echo $line; sleep 1; done\"\n", "line 1\n", "line 2\n", "line 3\n", "line 4\n", "line 5\n" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Starting job # 2 in a separate thread.\n" ] } ], "prompt_number": 13 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Remember, since the output of a background script is just the stdout pipe,\n", "you can read it as lines become available:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "import time\n", "tic = time.time()\n", "line = True\n", "while True:\n", " line = bashout.readline()\n", " if not line:\n", " break\n", " sys.stdout.write(\"%.1fs: %s\" %(time.time()-tic, line))\n", " sys.stdout.flush()\n" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "0.0s: line 1\n" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "1.0s: line 2\n" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "2.0s: line 3\n" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "3.0s: line 4\n" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "4.0s: line 5\n" ] } ], "prompt_number": 14 }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Configuring the default ScriptMagics" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The list of aliased script magics is configurable.\n", "\n", "The default is to pick from a few common interpreters, and use them if found, but you can specify your own in ipython_config.py:\n", "\n", " c.ScriptMagics.scripts = ['R', 'pypy', 'myprogram']\n", "\n", "And if any of these programs do not apear on your default PATH, then you would also need to specify their location with:\n", "\n", " c.ScriptMagics.script_paths = {'myprogram': '/opt/path/to/myprogram'}" ] } ], "metadata": {} } ] }