TransWikia.com

How to get Python bindings to work on the Raspberry Pi

Mathematica Asked by bobthechemist on December 15, 2020

There are several examples on this site on how to call Mathematica from Python. You can:

There are some good reasons to interact with Mathematica through Python, especially since the language is highly touted on the Raspberry Pi. The Python bindings for Mathematica aren’t available on the RPi version, however. Even pulling the bindings from another installation seems to have problems. So how does one get Mathematica and Python to talk nicely on the Raspberry Pi?

2 Answers

I have an idea :-)


Obtaining the code

While I've been told there's no reason not to share my findings about getting the Python bindings up and running, I wasn't given explicit permission to share the files, so I leave it up to you to find a copies of mathlink.c and setup.py which is found in the following directory (on PCs) and the comparable directory in Linux/Mac installs

Program FilesWolfram ResearchMathematica<Version>SystemFilesLinksPython

I have been successful with files from versions 8, 9 and 10.

Organizing your RPi

You need to copy a few files and clean up your RPi to make things run smoothly. Please note that while I've had no problems with these commands, I figure them out with trial and error. There is likely a more elegant way to do this.

  • Make sure you have python-dev installed (sudo apt-get install python-dev)
  • Copy /lib/arm-linux-gnueabihf/libuuid.so.1.3.0 to /usr/local/lib and rename to libuuid.so
  • Copy /opt/Wolfram/WolframEngine/10.0/SystemFiles/Links/Mathlink/DeveloperKit/Linux-ARM/CompilerAdditions/libML32i3.so to /usr/local/lib
  • Run sudo ldconfig

Modifying the code

A couple tweaks are needed in order to get the code to compile properly

  • mathlink.c
    • Add #define MLINTERFACE 3 at the top of the file, before the first #include line
  • setup.py
    • Change the version number to "10.0"
    • You need to make sure the directories are correct and an additional library needs to be linked. The first if statement should look like this
if(re.search(r'linux2',sys.platform)):
    setup(name="mathlink", version=pythonlinkversion,
        ext_modules=[
            Extension(
                "mathlink",
                ["mathlink.c"],
                include_dirs = ["/opt/Wolfram/WolframEngine/" + mathematicaversion + "/SystemFiles/Links/MathLink/DeveloperKit/Linux-ARM/CompilerAdditions"],
                library_dirs = ["/opt/Wolfram/WolframEngine/" + mathematicaversion + "/SystemFiles/Links/MathLink/DeveloperKit/Linux-ARM/CompilerAdditions"],
                libraries = ["uuid", "ML32i3", "m", "pthread", "rt"]
            )
        ]
    )

Install and test

You are now ready to build and install

python setup.py build
sudo python setup.py install

You can test with python -c 'import mathlink'. If that command throws no errors, you are in good shape.

What to do now?

You may have noticed two other python scripts in ...LinksPython, a gui front end and a text front end. Both of these seemed to work for me; however my Python programming skills are not good enough for these two programs to provide much learning assistance. Slowly, I put together some boilerplate python code (available here) that allows one to call a Mathematica kernel from within an interactive python session using

python -i bplate.py

To send an expression to the kernel, use sendexpression("<IN>") where is whatever Mathematica expression you can think of. (well, almost) Presently, I wrap everything in ToString so getting results is easy. To get the result of the computation, type getresult(). There's also a function qanda() that wraps the previous two together and saves on typing.

What works?

Functions like Prime, FactorInteger and GaussianMatrix all seem to work fine. Lists are returned as strings that must be parsed by Python. Symbols can be defined: f[x_]:=x^2 and the kernel is aware of the system (i.e. Directory, FileNames). We can even make WolframAlpha calls. You can export graphics, Export["test.png",Plot[Sin[x],{x,0, 4 Pi}]] and even view them with system calls, <<"!gpicview test.png" although you have to be patient.

What doesn't

Even though you can connect to the cloud via CloudConnect[<user>,<pass>], CloudEvaluate always throws an error. As mentioned earlier, to make this initial code easier to read, I'm returning strings so I don't have to go through a bunch of packet/token management which I don't yet understand.

But what else does it do?

The reason why I spent time on this was to deal with a problem in using Mathematica in scripts. On the RPi, it takes forever for Mathematica to load. I played some games with pipes when I tried to turn my Raspberry Pi into a Chemistry tutor and now I have a better way of doing that.

If you've looked at the bplate.py code there's a few lines at the end that can be uncommented. Once that's done, we can do something like this:

mkfifo mmpipe
tail -f mmpipe | python bplate.py &

and now we have an ever present Mathematica kernel just waiting for things to compute. All you have to do is echo to it:

echo "Prime[10]" > mmpipe

Answered by bobthechemist on December 15, 2020

As of 2019, there is now a Wolfram Client Library for Python which provides full access to the Wolfram Language from within Python. Therefore no mathlink craziness is needed. (Editorial: which is good, because trying to modify the previous answer to work with Python 3 has been a pain in the butt!)

The link above provides sufficient documentation to get one started, save for one slight modification needed to run on the Raspberry Pi. To summarize:

Install using pip with pip3 install wolframclient.

Assuming the above is successful, one can now run:

from wolframclient.evaluation import WolframLanguageSession
from wolframclient.language import wl
# Explicit mention of kernel was needed here
session = WolframLanguageSession('/usr/bin/wolfram') 
# perform Wolfram operations using a string for readability
session.evaluate('RandomVariate[NormalDistribution[5,0.1]]')
# perform the same operation using what the authors refer to as the wl factory
out = session.evaluate(wl.RandomVariate(wl.NormalDistribution(5,0.1)))
print(out)

This solution requires Python 3.5 or greater and Wolfram 11.3 or greater. I have tested on Python 3.7.3 and Mathematica 12.0.1 on a Raspberry Pi. Thanks to Dorian and Arnoud for all of their hard work on this feature.

Answered by bobthechemist on December 15, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP