##// END OF EJS Templates
handle closed event loop in async script magics...
handle closed event loop in async script magics leave other problems with asyncio implementation for another PR

File last commit:

r24322:1e1a3cd0
r27193:0fbbb2b5
Show More
Script Magics.ipynb
466 lines | 9.1 KiB | text/plain | TextLexer

Running Scripts from IPython

IPython has a %%script cell magic, which lets you run a cell in a subprocess of any interpreter on your system, such as: bash, ruby, perl, zsh, R, etc.

It can even be a script of your own, which expects input on stdin.

In [1]:
import sys

Basic usage

To use it, simply pass a path or shell command to the program you want to run on the %%script line, and the rest of the cell will be run by that script, and stdout/err from the subprocess are captured and displayed.

In [2]:
%%script python2
import sys
print 'hello from Python %s' % sys.version
hello from Python 2.7.9 (default, Jan 29 2015, 06:27:40) 
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.56)]
In [3]:
%%script python3
import sys
print('hello from Python: %s' % sys.version)
hello from Python: 3.4.2 |Continuum Analytics, Inc.| (default, Oct 21 2014, 17:42:20) 
[GCC 4.2.1 (Apple Inc. build 5577)]

IPython also creates aliases for a few common interpreters, such as bash, ruby, perl, etc.

These are all equivalent to %%script <name>

In [4]:
%%ruby
puts "Hello from Ruby #{RUBY_VERSION}"
Hello from Ruby 2.0.0
In [5]:
%%bash
echo "hello from $BASH"
hello from /usr/local/bin/bash

Capturing output

You can also capture stdout/err from these subprocesses into Python variables, instead of letting them go directly to stdout/err

In [6]:
%%bash
echo "hi, stdout"
echo "hello, stderr" >&2
hi, stdout
hello, stderr
In [7]:
%%bash --out output --err error
echo "hi, stdout"
echo "hello, stderr" >&2
In [8]:
print(error)
print(output)
hello, stderr

hi, stdout

Background Scripts

These scripts can be run in the background, by adding the --bg flag.

When you do this, output is discarded unless you use the --out/err flags to store output as above.

In [9]:
%%ruby --bg --out ruby_lines
for n in 1...10
    sleep 1
    puts "line #{n}"
    STDOUT.flush
end
Starting job # 0 in a separate thread.

When you do store output of a background thread, these are the stdout/err pipes, rather than the text of the output.

In [10]:
ruby_lines
Out[10]:
<open file '<fdopen>', mode 'rb' at 0x10a4be660>
In [11]:
print(ruby_lines.read())
line 1
line 2
line 3
line 4
line 5
line 6
line 7
line 8
line 9

Arguments to subcommand

You can pass arguments the subcommand as well, such as this example instructing Python to use integer division from Python 3:

In [12]:
%%script python2 -Qnew
print 1/3
0.333333333333

You can really specify any program for %%script, for instance here is a 'program' that echos the lines of stdin, with delays between each line.

In [13]:
%%script --bg --out bashout bash -c "while read line; do echo $line; sleep 1; done"
line 1
line 2
line 3
line 4
line 5
Starting job # 2 in a separate thread.

Remember, since the output of a background script is just the stdout pipe, you can read it as lines become available:

In [14]:
import time
tic = time.time()
line = True
while True:
    line = bashout.readline()
    if not line:
        break
    sys.stdout.write("%.1fs: %s" %(time.time()-tic, line))
    sys.stdout.flush()
0.0s: line 1
1.0s: line 2
2.0s: line 3
3.0s: line 4
4.0s: line 5

Configuring the default ScriptMagics

The list of aliased script magics is configurable.

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:

c.ScriptMagics.scripts = ['R', 'pypy', 'myprogram']

And if any of these programs do not appear on your default PATH, then you would also need to specify their location with:

c.ScriptMagics.script_paths = {'myprogram': '/opt/path/to/myprogram'}