16. Python interoperability
As mentioned in the beginning of this book, Mojo is very close to Python in terms of syntax. However, Mojo and Python are semantically two completely different languages, though they share very similar syntax. Python has a huge ecosystem behind it, built over many decades. Mojo allows the developer to leverage this huge ecosystem, with its Python integration capability.
The integration of Mojo with Python is built on a key insight that from a practical point of view, all Python objects can be represented with a single type. In Mojo it is represented by the PythonObject
struct. Mojo uses the actual CPython interpreter for interoperability. The usage of CPython in Mojo enables high fidelity integration with Python, and ensures that the Python objects behave as expected.
16.1. Importing a Python module
Mojo has module named python
that encapsulates all of the Python integration. Within the python
module, there is the facade object that provides the entry point for many of the Python integration capabilities.
Importing a Python module is as simple as using the Python.import_module
method call, passing it the module name. In case a module does not exist, ensure that the module is installed using the pip
or equivalent command. Mojo also supports Python virtual environments.
The following code listing provides an example on how to import Python modules and how to use objects from Python.
from python import Python
var difflib = Python.import_module("difflib")
var list1 = ["One", "Two", "Three", "Four"]
var list2 = ["One", "Two", "Three"]
var differ = difflib.HtmlDiff() # Get instance of HtmlDiff class.
var diff = differ.make_file(list1, list2)
print(diff)
16.2. Evaluating Python expressions
You can evaluate Python expressions using Python.evaluate
method.
print(Python.evaluate("1+2"))
Since Python treats functions as first class, you can even use Python.evaluate
to access Python’s built-in functions.
var str_fn = Python.evaluate("str")
print(str_fn("ABC") <= str_fn("XYZ"))
Note in the above code listing, how transparently we can transfer Mojo string literals to the Python function, and how seamlessly Mojo operators work over Python objects, invoking the right Python dunder methods. One important constraint is that only PythonObject
struct can be passed to and from Python. In the case of Mojo string literals, PythonObject
has a constructor that takes StringLiteral
, resulting in implicit conversion from StringLiteral
to a PythonObject
instance. PythonObject
has many such constructors for the various Mojo built-in types. PythonObject
also implements many traits that enable it to be used within functions such as len
, int
, str
and so on.
16.3. Other useful Python functions
You can use native Python objects like list
and dict
using corresponding static methods exposed by Python
. Python
also exposes type
function from Python and can be used to determine the underlying type of the PythonObject
struct.
var a_list = Python.list()
a_list.append("First element")
a_list.append("Second element")
print(a_list)
print(Python.type(a_list))