Python interoperability
Because Mojo uses a Pythonic syntax, its easy to start reading and writing Mojo when coming from Python. Mojo also optimizes for ease of use in across the Python-Mojo language boundary, with built-in support for both calling into Python from Mojo, and calling into Mojo from Python.


The common API for interoperability in both directions is the
PythonObject
type, which
wraps a Python object within Mojo.
In Mojo, you can import Python modules, construct Python objects, and call
Python functions and methods directly. Mojo will first load the CPython
interpreter as a dynamic library (called libpython.dylib
on macOS), and use
that interpreter to execute Python code. For example:
from python import Python
fn main():
# Loads CPython dynamically behind the scenes; returns a PythonObject
var res = Python.evaluate("2 + 2")
from python import Python
fn main():
# Loads CPython dynamically behind the scenes; returns a PythonObject
var res = Python.evaluate("2 + 2")
Calling into Mojo from Python is different. Because Mojo is a compiled language, we can't directly "evaluate" Mojo code. Instead, Mojo code must declare up front which functions and types are available to be called from Python. For example:
@export
fn PyInit_mojo_module() -> PythonObject:
try:
var m = PythonModuleBuilder("mojo_module")
m.def_function[mojo_greet]("mojo_greet", docstring="Say hello from Mojo")
return m.finalize()
except e:
return abort[PythonObject](String("error creating Python Mojo module:", e))
fn mojo_greet(name: PythonObject):
print("Hello to", name, "from Mojo ๐")
@export
fn PyInit_mojo_module() -> PythonObject:
try:
var m = PythonModuleBuilder("mojo_module")
m.def_function[mojo_greet]("mojo_greet", docstring="Say hello from Mojo")
return m.finalize()
except e:
return abort[PythonObject](String("error creating Python Mojo module:", e))
fn mojo_greet(name: PythonObject):
print("Hello to", name, "from Mojo ๐")
By defining a suitable PyInit_*()
function, Mojo performs the necessary
low-level binding calls to inform Python how to call Mojo code:
import max._mojo.mojo_importer
import mojo_module
mojo_module.mojo_greet("Python")
import max._mojo.mojo_importer
import mojo_module
mojo_module.mojo_greet("Python")
(Although it's not quite that simple yet.)
These quick examples give you a taste of what interoperability looks like for Python and Mojo. Flexible interop enables you to move incrementally and efficiently. By embracing both directions of language interop, you can choose how to use Mojo in a way that works best for your use case.
To learn more about bridging Python โ Mojo, continue reading:
Was this page helpful?
Thank you! We'll create more content like this.
Thank you for helping us improve!