Making use of existing Python code from Julia and RxInfer
RxInfer
Julia
PythonCall
Python
Author
Kobus Esterhuysen
Published
August 18, 2024
Modified
August 28, 2024
While practising Active Inference making use of RxInfer it would be beneficial to sometimes make use of existing code in Python. For example, using existing data generation code, or, code that simulates the dynamics of the environment can save a lot of time and effort. The PythonCall package in Julia bridges the gap between Julia and Python, enabling seamless integration of Python code within Julia projects. This package is particularly valuable for Julia developers who want to leverage the extensive libraries and tools available in Python without leaving the Julia environment.
With PythonCall, you can directly call Python functions, use Python objects, and manage Python packages as if they were native to Julia. This opens up a world of possibilities, allowing you to combine Julia’s high-performance computing capabilities with Python’s rich ecosystem.
In this project, we will explore how to set up PythonCall, import Python libraries, and execute Python code within Julia. You will see some examples to integrate Python’s functionality into Julia projects, maximizing your productivity and the capabilities of your codebase.
versioninfo() ## Julia version
Julia Version 1.10.4
Commit 48d4fd48430 (2024-06-04 10:41 UTC)
Build Info:
Official https://julialang.org/ release
Platform Info:
OS: Linux (x86_64-linux-gnu)
CPU: 12 × Intel(R) Core(TM) i7-8700B CPU @ 3.20GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-15.0.7 (ORCJIT, skylake)
Threads: 1 default, 0 interactive, 1 GC (on 12 virtual cores)
Environment:
JULIA_NUM_THREADS =
Setting Up PythonCall in Julia
To effectively use the PythonCall package in Julia, you need to ensure that your environment is properly set up. This involves installing PythonCall, configuring Python environments, and ensuring that Python packages are accessible. Below are the key steps to set up PythonCall:
1. Install PythonCall
First, you need to install the PythonCall package in Julia. Open your Julia REPL and run:
Activating project at `~/.julia/environments/v1.10`
Resolving package versions...
No Changes to `~/.julia/environments/v1.10/Project.toml`
No Changes to `~/.julia/environments/v1.10/Manifest.toml`
This command installs PythonCall and its dependencies. We also use some other packages.
Resolving package versions...
No Changes to `~/.julia/environments/v1.10/Project.toml`
No Changes to `~/.julia/environments/v1.10/Manifest.toml`
Resolving package versions...
No Changes to `~/.julia/environments/v1.10/Project.toml`
No Changes to `~/.julia/environments/v1.10/Manifest.toml`
PythonCall requires a working Python installation. By default, PythonCall will use the Python installation that it finds in your system’s PATH. However, you can also specify a different Python installation or create a new one using CondaPkg or other package managers.
You can check which Python is being used by PythonCall with:
# ENV["PYTHON"] = "/home/vscode/.julia/environments/v1.10/.CondaPkg/env/bin/python" # Replace with the path to your Python executable# Check the Python executable againpython_executable =pyimport("sys").executableprintln("Python executable: ", python_executable)
This will display the path to the Python executable being used by PythonCall.
3. Managing Python Packages
There are multiple ways to manage Python packages for use with PythonCall:
Using an Existing Python Environment: If you already have a Python environment set up with the required packages, PythonCall can use it directly. Ensure that the environment is active in your shell or specify its path explicitly.
Creating and Managing Python Environments with CondaPkg: You can create isolated Python environments within Julia using CondaPkg. This method is particularly useful if you want to manage dependencies within your Julia project:
Using Virtualenv or Venv: If you prefer to use virtualenv or venv, you can activate the environment and then launch Julia, ensuring PythonCall uses this environment.
This example shows how to convert a Python list to a Julia vector using pyconvert.
2. Mutability Preservation
PythonCall preserves the mutability of objects. For example, appending to a Python list from Julia:
x = ["foo", "bar"]Py(x).append("baz")@show x
x = ["foo", "bar", "baz"]
3-element Vector{String}:
"foo"
"bar"
"baz"
In this example, the Python list is directly modified, and the changes are reflected in the original Julia object. These examples demonstrate the basic functionality of PythonCall, including module importation, type conversion, and mutability preservation.
3. Using the re package
re =pyimport("re")
Python: <module 're' from '/home/vscode/.julia/environments/v1.10/.CondaPkg/env/lib/python3.11/re/__init__.py'>
words = re.findall("[a-zA-Z]+", "PythonCall.jl is very useful!")