Python bindings for Woxi, an interpreter for a subset of the Wolfram Language implemented in Rust. Woxi is a computer algebra system (CAS), so computations are solved symbolically.
pip install woxiimport woxi
woxi.interpret("Plus[1, 2]")
# => '3'
woxi.interpret("Integrate[x^2, x]")
# => 'x^3/3'
# Session state persists across calls (per thread):
woxi.interpret("x = 42;")
woxi.interpret("x + 1")
# => '43'
woxi.clear_state()
# Capture stdout, graphics, sound, and warnings:
res = woxi.evaluate('Print["hi"]; Plot[Sin[x], {x, 0, 10}]')
res.stdout # => 'hi\n'
res.graphics # => '<svg …' (SVG markup)
# Reproducible random numbers:
woxi.seed_rng(1)
# Errors raise woxi.WolframError:
try:
woxi.interpret("1 +")
except woxi.WolframError as err:
print(err)Results are also available as a structured tree, so you don't have to parse Wolfram output text to use them:
import woxi
woxi.evaluate("1/3 + 1/6").expr
# => Expr(Symbol("Rational"), [1, 2])
woxi.evaluate("Solve[x^2 == 2, x]").expr
# => [[Expr(Symbol("Rule"), [Symbol("x"), …])], …]The tree mirrors Wolfram's FullForm,
so x + y is Plus[x, y] and a/b is Times[a, Power[b, -1]]
no matter how they were written.
Only exact, total mappings use native Python types:
| Wolfram | Python |
|---|---|
Integer, BigInteger |
int |
Real |
float |
String |
str |
List[…] |
list |
| symbol or constant | woxi.Symbol |
| arbitrary-precision real | woxi.BigReal |
| everything else | woxi.Expr(head, args) |
woxi.to_python converts the rest
when convenience matters more than exactness —
Rational to fractions.Fraction, Complex to complex,
Association to dict, and True/False/Null
to True/False/None:
woxi.to_python(woxi.evaluate("1/3 + 1/6").expr)
# => Fraction(1, 2)
woxi.to_python(woxi.evaluate('<|"a" -> 1|>').expr)
# => {'a': 1}Trees also go the other way, so Python values reach an evaluation without string concatenation:
from woxi import wl
woxi.evaluate_expr(wl.Integrate(wl.Power(wl.x, 2), wl.x)).result
# => 'x^3/3'
woxi.evaluate_expr(wl.Total([1, 2, 3, 4])).result
# => '10'
# A str argument is data here, never code:
woxi.evaluate_expr(wl.StringLength("1 + 1")).result
# => '5'wl.<name> is the symbol of that name and calling it applies it,
so any Wolfram expression can be built without quoting.
woxi.parse_expr parses source into a tree without evaluating it:
woxi.parse_expr("1 + 1")
# => Expr(Symbol("Plus"), [1, 1])The package also installs a woxi command:
woxi eval 'Plus[1, 2]' # Evaluate an expression
woxi run script.wls # Run a Wolfram Language file
woxi repl # Interactive sessionFor the full-featured native CLI (including the Jupyter kernel),
install the Rust binary instead: cargo install woxi.
The package is built with maturin and requires a Rust toolchain:
cd woxi-py
pip install maturin
maturin develop # Build and install into the active virtualenvRun the tests with:
python -m pytest tests/AGPL-3.0-or-later