Skip to content

Instantly share code, notes, and snippets.

@fperez
Last active December 14, 2015 05:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fperez/5034046 to your computer and use it in GitHub Desktop.
Save fperez/5034046 to your computer and use it in GitHub Desktop.
Julia magics, work with @JeffBezanson
Display the source blob
Display the rendered blob
Raw
{
"metadata": {
"name": "JuliaMagic"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Experimental Julia magics in IPython"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<img src=\"files/Dean-Potter.jpg\" width=\"100%\"></img>"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%load_ext juliamagic"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 1
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%julia 1+2+3"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 2,
"text": [
"6"
]
}
],
"prompt_number": 2
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%julia 1+2+3.0"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 3,
"text": [
"6.0"
]
}
],
"prompt_number": 3
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%julia\n",
"\n",
"sum([1 2;3 4]^2)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 4,
"text": [
"54"
]
}
],
"prompt_number": 4
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%julia\n",
"\n",
"sum([1 2;3 4.0]^2)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 5,
"text": [
"54.0"
]
}
],
"prompt_number": 5
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For some reason, multiline blocks aren't executing quite right, so for now I'm putting them line by line. Need to investigate further. But even function definitions work:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%julia fib(n) = n < 2 ? n : fib(n-1) + fib(n-2)\n",
"%julia fib(10)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 6,
"text": [
"55"
]
}
],
"prompt_number": 6
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And once defined, they can be used as the state of the Julia interpreter is persistent:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%julia\n",
"fib(20)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 7,
"text": [
"6765"
]
}
],
"prompt_number": 7
},
{
"cell_type": "code",
"collapsed": false,
"input": [],
"language": "python",
"metadata": {},
"outputs": []
}
],
"metadata": {}
}
]
}
"""Julia magics for IPython.
"""
#-----------------------------------------------------------------------------
# Copyright (C) 2013 The IPython Development Team
#
# Distributed under the terms of the BSD License. The full license is in
# the file COPYING, distributed as part of this software.
#-----------------------------------------------------------------------------
# Global to ensure we don't try to initialize the Julia interpreter more than
# once, so this can actually be reloaded.
import ctypes
import sys
from IPython.core.magic import ( Magics, magics_class,
line_cell_magic )
class JuliaMagicError(Exception):
pass
@magics_class
class JuliaMagics0(Magics):
"""A set of magics useful for interactive work with Julia.
"""
def __init__(self, shell):
"""
Parameters
----------
shell : IPython shell
"""
global _julia_initialized
super(JuliaMagics0, self).__init__(shell)
# Ugly hack to register the julia interpreter globally so we can reload
# this extension without trying to re-open the shared lib, which kills
# the python interpreter. Nasty but useful while debugging
if hasattr(sys, '_julia_initialized'):
j = sys._julia_initialized
else:
j = ctypes.CDLL('libjulia-release.so', ctypes.RTLD_GLOBAL)
j.jl_init("/home/fperez/tmp/src/julia/usr/lib")
sys._julia_initialized = j
j.jl_typeof_str.restype = ctypes.c_char_p
unbox_map = dict(float32 = ctypes.c_float,
float64 = ctypes.c_double,
int32 = ctypes.c_int,
int64 = ctypes.c_longlong,
)
j_unboxers = {}
for jname, ctype in unbox_map.iteritems():
junboxer = getattr(j, 'jl_unbox_' + jname)
junboxer.restype = ctype
j_unboxers[jname] = junboxer
self._junboxers = j_unboxers
self._j = j
@line_cell_magic
def julia(self, line, cell=None):
'''
Execute code in Julia, and pull some of the results back into the
Python namespace.
'''
src = str(line if cell is None else cell)
ans = self._j.jl_eval_string(src)
anstype = self._j.jl_typeof_str(ans).lower()
#print 'anstype:', anstype
try:
unboxer = self._junboxers[anstype]
except KeyError:
#print "Unboxer not found for return type:", anstype # dbg
return None
else:
return unboxer(ans)
@magics_class
class JuliaMagics(Magics):
"""A set of magics useful for interactive work with Julia.
"""
def __init__(self, shell):
"""
Parameters
----------
shell : IPython shell
"""
global _julia_initialized
super(JuliaMagics, self).__init__(shell)
# Ugly hack to register the julia interpreter globally so we can reload
# this extension without trying to re-open the shared lib, which kills
# the python interpreter. Nasty but useful while debugging
if hasattr(sys, '_julia_initialized'):
j = sys._julia_initialized
self._j = j
return
j = ctypes.CDLL('libjulia-release.so', ctypes.RTLD_GLOBAL)
j.jl_init("/home/fperez/tmp/src/julia/usr/lib")
sys._julia_initialized = j
self._j = j
j.jl_typeof_str.restype = ctypes.c_char_p
j.jl_unbox_voidpointer.restype = ctypes.py_object
self.jcall('using PyCall')
self.jcall('pyinitialize("%s")' % sys.executable)
jpyobj = self.jcall('PyObject')
self._j_py_obj = jpyobj
def jcall(self, src):
print '>> J:', src
sys.stdout.flush()
ans = self._j.jl_eval_string(src)
anstype = self._j.jl_typeof_str(ans)
print 't :', anstype
if anstype == "ErrorException":
raise JuliaMagicError("ErrorException in Julia: %s" %src)
else:
return ans
@line_cell_magic
def julia(self, line, cell=None):
'''
Execute code in Julia, and pull some of the results back into the
Python namespace.
'''
j = self._j
tstr = self._j.jl_typeof_str
src = str(line if cell is None else cell)
ans = self.jcall(src)
anstype = tstr(ans)
print 'anstype:', anstype
print 'pyo', tstr(self._j_py_obj)
xx = j.jl_call1(self._j_py_obj, ans)
print 'xx type' , tstr(xx)
sys.stdout.flush()
pyans = j.jl_get_field(xx, 'o')
return j.jl_unbox_voidpointer(pyans)
__doc__ = __doc__.format(
JULIA_DOC = ' '*8 + JuliaMagics.julia.__doc__,
)
def load_ipython_extension(ip):
"""Load the extension in IPython."""
ip.register_magics(JuliaMagics0)
#ip.register_magics(JuliaMagics)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment