#!/usr/bin/env python # coding: utf-8 # # 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]: get_ipython().run_cell_magic('script', 'python2', "import sys\nprint 'hello from Python %s' % sys.version\n") # In[3]: get_ipython().run_cell_magic('script', 'python3', "import sys\nprint('hello from Python: %s' % sys.version)\n") # IPython also creates aliases for a few common interpreters, such as bash, ruby, perl, etc. # # These are all equivalent to `%%script ` # In[4]: get_ipython().run_cell_magic('ruby', '', 'puts "Hello from Ruby #{RUBY_VERSION}"\n') # In[5]: get_ipython().run_cell_magic('bash', '', 'echo "hello from $BASH"\n') # ## 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]: get_ipython().run_cell_magic('bash', '', 'echo "hi, stdout"\necho "hello, stderr" >&2\n') # In[7]: get_ipython().run_cell_magic('bash', '--out output --err error', 'echo "hi, stdout"\necho "hello, stderr" >&2\n') # In[8]: print(error) print(output) # ## 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]: get_ipython().run_cell_magic('ruby', '--bg --out ruby_lines', 'for n in 1...10\n sleep 1\n puts "line #{n}"\n STDOUT.flush\nend\n') # 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 # In[11]: print(ruby_lines.read()) # ## 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]: get_ipython().run_cell_magic('script', 'python2 -Qnew', 'print 1/3\n') # 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]: get_ipython().run_cell_magic('script', '--bg --out bashout bash -c "while read line; do echo $line; sleep 1; done"', 'line 1\nline 2\nline 3\nline 4\nline 5\n') # 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() # ## 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 apear on your default PATH, then you would also need to specify their location with: # # c.ScriptMagics.script_paths = {'myprogram': '/opt/path/to/myprogram'}