Julia is a young programming language. This means that its native libraries are immature. We are in a time when Julia is a mature enough as a language that it is out-pacing its libraries.
One way to use mature libraries from a young language is to borrow them from another language. In this case, we’ll be borrowing from Python. (Julia can also easily wrap libraries from C or Fortran. In fact, this capability was important in combination with Python’s great C-interface to make calling Python from Julia do-able.)
Python from Julia: PyCall.jl
Calling Python from Julia requires PyCall.
You can get it using
Let’s start with a “Hello, World” scale example.
using PyCall pyeval("2+2") #=> 4 pyeval("str(5)") #=> "5" # doing things by hand, for fun :) math = pyimport(:math) #=> PyObject <module 'math'> pycall(math["sin"],Float64,1) #=> 0.8414709848078965
Using Python Libraries from Julia
For a quick practical example of Python libraries filling in Julia’s current gaps, we can use Python’s matplotlib for graphing. If you also install matplotlib, you can run this fun code snippet I found on the mailing list. If you run it, it will pop up a window with a graph of a nice dotted, squiggley, red line.
using PyCall @pyimport pylab x = linspace(0,2*pi,1000); y = sin(3*x + 4*cos(2*x)); pylab.plot(x, y; color="red", linewidth=2.0, linestyle="--") pylab.show()
pylab is the name for the Python module that includes matplotlib and numpy
in a single namespace, according to matplotlib’s docs;
it is the recommended interface to matplotlib.
@pyimport is a Julia macro that is equivalent to a
using statement on the Julia equivalent of the Python module.
What this means is that we can now use
pylab as if it’s a Julia module, which is what the dot-notation (
pylab.plot) is taking advantage of.
We use two functions from
Notice that we don’t have to do anything special when we invoke them:
they look just like Julia functions, right down to the keyword arguments.
Julia from Python: the julia module
This is the less polished direction;
it’s not really intended for public consumption yet.
To get the Python module that you need to call Julia,
git clone https://github.com/JuliaLang/IJulia.jl.
Then, inside the
IJulia.jl/python/ folder, run
python setup.py install. (you may need
sudo on that last command)
First, the opening incantation:
import julia j = julia.Julia()
The second line will take a while to run; it’s starting and setting up Julia.
Now, you’ll be able to call Julia from the Python REPL. For example:
j.run("2+2") #=> 4 j.run("sin(pi)") #=> 1.2246467991473532e-16 j.run("x = 5") #=> 5 j.run("x += 2") #=> 7 j.run("x") #=> 7
Let’s be best friends: Mutual Recursion.
This section is a code example. We’ll start at the top, and then wander down through the implementation. You can find all the code on github.
If you clone that repo, you can open a Python REPL up inside that folder and run the following:
import pyiseven pyiseven.even(5)
As one would hope, you’ll get
import line probably took a really long time to load; the
even function seems pretty straight forward given its name and behavior.
But, let’s take a look at
import julia j = julia.Julia() def even(x): j.run("using IsOdd") return not j.run("IsOdd.odd(" + str(x) + ")")
Oh no! This looks terribly inefficient: even if Julia is 20x faster than Python, calling another programming language to figure out if your number is odd is a bad plan.
Maybe we should take a look at
module IsOdd using PyCall @pyimport pyiseven function odd(x) if x == 1 true elseif x == 0 false else pyiseven.even(x-1) end end end
Oh no! It gets worse!
We make another function call back into Python’s
even function on every call to Julia’s
That means that it takes two function calls (and two trips between languages) for each increment of
(In fact, if you call
pyiseven.even(201) (or greater), then the stack explodes, unfortunately.)
If you find that your production code is too slow because you’re using mutual recursion between nine different languages, blame Dan Luu for this terrible idea.
You should really check out PyCall, which does a great job of translating between Python and Julia values and modules.
If you’ve been using IPython notebook, then you should also try IJulia notebook. (Same frontend, different language). You may have noticed that the IJulia project’s repo is the origin of that Python