How to Integrate Julia Code Within a Python Program

By: Great Lakes Consulting

Re-posted from: https://blog.glcs.io/julia-python-juliacall

This post was written by Steven Whitaker.

Ever wish your Python code could run fasteron heavy calculations or simulations?With juliacall,you can call Julia straight from Pythonand instantly access blazing-fast performanceand powerful scientific libraries,all without rewriting your existing code.Supercharge your Python workflows today andelevate your data science and engineering projectsto new heights!

In this Julia for Devs post,learn step-by-step how to install andutilize juliacall,enabling you toboost critical code performanceeffortlessly,without rewriting your entire project.Unlock the powerful combination ofPythons vast ecosystemand Julias speed,making it easy to experiment,optimize,or gradually migrate key components.

Let’s dig in!

Installing juliacall

Installation is a breeze,all you need is

pip install juliacall

You can test your installationby running the following in Python:

from juliacall import Main as jl

The first time this runs,it will install the Julia packagesneeded for communicatingbetween Julia and Python.

Then you can try it out:

import numpy as npA = np.array(jl.rand(5, 3))x = np.array(jl.randn(3))y = A @ x

Great,Julia-Python interoperabilityworks for this small example!Now let’s seehow we can extend thisto a larger example.

Calling Custom Code

In practice,we might have written some custom code in Juliathat we want to integrateinto our Python workflow.Let’s walk through the processof this integration.

Julia Code

Typically,the Julia code will be organizedinto a package,including its own package environmentand dependencies.

We’ll work with an examplethat runs a simulationusing OrdinaryDiffEq.jl and StaticArrays.jl.The example packagehas the following directory structure:

JuliaExample Project.toml src     JuliaExample.jl

The Project.toml has the following content:

name = "JuliaExample"uuid = "0b6476de-1cea-499f-93be-749bc74a9c07"authors = ["Author Name <address@email.com>"]version = "0.1.0"[deps]OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"

And JuliaExample.jl contains:

module JuliaExampleusing OrdinaryDiffEq: ODEProblem, Tsit5, solveusing StaticArrays: SVectorstruct Params    ::Float64    ::Float64    ::Float64endfunction f(u, p, t)    (; , , ) = p    dx =  * (u[2] - u[1])    dy = u[1] ( - u[3]) - u[2]    dz = u[1] * u[2] -  * u[3]    return SVector(dx, dy, dz)endfunction simulate(u0, t_start, t_end, , , )    u0 = SVector{3, Float64}(u0)    tspan = (t_start, t_end)    p = Params(, , )    prob = ODEProblem{false}(f, u0, tspan, p)    sol = solve(prob, Tsit5())endend

Python Code

We have our custom Julia code,so now let’s seewhat our Python workflow looks likethat calls out to Julia.

We’ll have our code organizedin the following directory structure:

python_example pyproject.toml scripts    run.py src     python_example         __init__.py         analysis.py

The main functionality of our Python codeis in analysis.py:

from juliacall import Main as jljl.seval("using JuliaExample: simulate")import numpy as npimport matplotlib.pyplot as pltdef simulate(*args):    result = jl.simulate(*args)    t = np.array(result.t)    sol = np.array([np.array(u) for u in result.u])    return t, soldef plot_results(t, sol):    plt.figure(figsize=(10, 6))    labels = ["x", "y", "z"]    colors = ["tab:blue", "tab:orange", "tab:green"]    for i in range(3):        plt.plot(t, sol[:, i], label=labels[i], color=colors[i])    plt.xlabel("Time [s]")    plt.ylabel("Value")    plt.title("Solution Components Over Time")    plt.legend()    plt.grid(True)    plt.tight_layout()    plt.show()

This code provides two functions:one for calling out to Juliato run a simulation,and another for plotting the simulation results.

Let’s break down some of this codeto see how Julia is incorporated:

  • from juliacall import Main as jl
    We saw this earlier;this is how to load juliacall.
  • jl.seval("using JuliaExample: simulate")
    Here,we load our Julia package,specifically bringing the function simulateinto scope.
  • The Python function simulatecalls the Julia simulate,passing along all its inputs:
    result = jl.simulate(*args)
    The Python functionthen does some processingto convert the Julia resultsinto something more easily utilizedby further Python processing.

This functionality is exercisedin the run.py script:

from python_example import simulate, plot_resultsimport numpy as npu0 = np.array([1, 0, 0])t_start = 0t_end = 100alpha = 10beta = 28gamma = 8/3t, sol = simulate(u0, t_start, t_end, alpha, beta, gamma)plot_results(t, sol)

Finally,for completeness,here’s __init__.py:

from .analysis import simulate, plot_results

Finding Julia

We have all our code set up,so now we need Pythonto be able to find the Julia codeso we can call out to it.In other words,we need the Julia package environmentused by juliacallto have JuliaExample as a dependency.

We can accomplish thisby creating a juliapkg.json filein our Python project directory(i.e., python_example/juliapkg.json).The file should contain the following JSON:

{    "packages": {        "JuliaExample": {            "uuid": "0b6476de-1cea-499f-93be-749bc74a9c07",            "path": "path/to/JuliaExample",            "dev": true        }    }}

Note that the uuid hereneeds to match the uuidin JuliaExample/Project.toml.And the "path" and "dev": true fields are necessarybecause our Julia package exists locally on our machine;it is not a registered Julia package.See the juliacall docsfor more information about juliapkg.json.

Putting It Together

Now we have all the components we need:Python code to run,Julia code to call out to,and juliapkg.json to tell juliacallwhere to find our Julia code.

So, what happens when we run run.py?

The first time it is run,juliacall will set up the Julia package environment,installing the dependencies of JuliaExample.Then, the script proceeds to run the simulation(calling out to Julia to do so)and plot the results:

Simulation results

Awesome,we now have a working exampleshowing how to call out to Juliafrom a Python project!

Summary

In this post,we saw how to install and use juliacallto call out to Julia from within Python.We looked at a trivial exampleas well as a more realistic exampleof integrating custom Julia codeinto a Python project.

What custom Julia codedo you want to integrateinto your Python projects?Contact us, and we can make it happen!

Additional Links

  • PythonCall.jl
    • One cool thing about juliacallis it is maintained in the same GitHub repoas PythonCall,which is the recommended wayto call Python code from Julia.
  • GLCS Modeling & Simulation
    • Connect with us for Julia Modeling & Simulation consulting.
]]>