Tim Perkins

Matlab in Python in Matlab?

pymex

Description

Let's say a programmer is writing a Matlab script, but needs to accomplish some task which Matlab can't do natively. The programmer has a couple of options, but he or she will most likely have to write some Java or C / C++. But what if there is already a Python solution? pymex allows the programmer to use Python in Matlab.

pymex embeds a Python interpreter in Matlab, allowing Matlab programmers write parts of their scripts in Python. Programmers are also able to use Python modules in Matlab. pymex aims to be easy to use, simply pass it a string containing Python script and it will evaluate it. A special matlab module is provided to move data in between Matlab and Python (with restrictions). pymex is still under development, if you have questions or comments send me an email.

Embedded and Extended

pymex both embeds and extends Python. The embedding part is strait forward, the Python interpreter is embedded in Matlab. The extending part is were things get interesting. pymex provides a special matlab module which only available when running Python inside of Matlab. This module allows the programmer to move data back and forth between Matlab and Python representations. The matlab module also lets programmers print to Matlab's command window from Python.

The Matlab Module

matlab

The module adding Matlab functionality. Import this to use the following functions.

import matlab

matlab.mex_print(...)

Print all arguments to the Matlab command window. Works similarly to Python's normal print function.

matlab.mex_print('hello', x, y, z)

matlab.pull(name1, name2, ...) => var1, var2, ...

Import Matlab variables, move Matlab arrays to Python sequences. For each variable name given as an argument, return the value of the variable in Matlab with that name, in the same order. The Matlab variable has "caller" scope. Uses Matlab's evalin function.

x, y, z = matlab.pull("x", "y", "z")

matlab.push(name1, var1, name2, var2, ...)

Export Matlab variables, move Python sequences to Matlab arrays. For each variable name and value pair, create a Matlab variable with that name and value. The Matlab variable has "caller" scope. Uses Matlab's assignin function.

matlab.push("x", x, "y", y", "z", z)

Examples

The following is an example of pymex's use. The following code moves a variable from the Matlab workspace to the Python script. That value is then broadcasted over the LAN using the Spread Toolkit.

>> pymex('import matlab')

ans =
     1

>> pymex('import spread')

ans =
     1

>> pymex('mbox = spread.connect("4803@192.168.10.100")')

ans =
     1

>> pymex('mbox.join("lalala")')

ans =
     1

>> x = [1 2 3; 4 5 6]

x =
     1     2     3
     4     5     6

>> pymex('x = matlab.pull("x")')

ans =
     1

>> pymex('matlab.mex_print(x)')
((1.0, 2.0, 3.0), (4.0, 5.0, 6.0))

ans =
     1

>> pymex('mbox.multicast(spread.SAFE_MESS, "lalala", str(x))')

ans =
     1

pymex allows data to move in between the two interpreters using the "pull" and "push" functions. The data which can be moved is limited to scalars, strings, and multi-dimensional arrays. Multidimensional arrays are native to Matlab, and are represented in Python by sequences of sequences. A multidimensional array must be a sequence and have nested subsequences for each dimension. The terminal subsequences must contain types which are numeric.

>> pymex('y = "hello world"')

ans =
     1

>> pymex('matlab.mex_print(y)')
hello world

ans =
     1

>> y
??? Undefined function or variable 'y'.

>> pymex('matlab.push("y", y)')

ans =
     1

>> y

y =
hello world

pymex typically accepts a Python script as a single string. For your convenience, pymex can also accept a script as a cell array of strings. This makes it much easier to escape a Python script in Matlab.

>> clear pymex
>> script = {
'import matlab',
'for x in [1, 2, 3]:',
'  matlab.mex_print("durp %d" % x)'
}

script = 
    'import matlab'
    'for x in [1, 2, 3]:'
    '  matlab.mex_print("durp %d" % x)'

>> pymex(script)
durp 1
durp 2
durp 3

ans =
     1

Threading

pymex supports parallelization! Programmers can use both the threading and multiprocessing modules. Threads are useful for I/O, but they are not truely parallel because of the Global Interpreter Lock (GIL). Processes don't have to worry about the GIL, so they are better for parallel computation.

>> pyscript = {
'import Queue'
'import threading'
'class FilePrinterThread(threading.Thread):'
'  def __init__(self, filename, q):'
'    threading.Thread.__init__(self)'
'    self.daemon = True'
'    self.q = q'
'    self.filename = filename'
'  def run(self):'
'    while True:'
'      s = self.q.get()'
'      with open(self.filename, "a") as f:'
'        f.write("%s\n" % s)'
'      f.close()'
'      self.q.task_done()'
'queue = Queue.Queue()'
'thread = FilePrinterThread("durp.txt", queue)'
'thread.start()'
};

>> pymex(pyscript)

ans =
     1

>> pymex('queue.put("hello")')

ans =
     1

>> pymex('queue.put("testing")')

ans =
     1

>> pymex('queue.put("the end")')

ans =
     1

>> ! cat durp.txt
hello
testing
the end

WARNING! Programmers need to consider thread-safety. Matlab's mex interface is not thread-safe. By extension, the matlab module is not thread-safe. Don't use the matlab module in a thread! There will be memory access violations! It will segfault!

Why?

Why not?

One day I wanted to run a Python script from Matlab. I tried using Matlab's system command, but getting a useful result required alot of text parsing, which was annoying and slow. Also, the Python interpreter had to be initialized and finalized on each call. I also tried using named pipes, but that seemed kind of messy to me. I decided I could do better, so I wrote pymex.

License

pymex is covered by the DSB License.

Download

Sorry, for now pymex is linux only.

pymex_0.3.zip

pymex is also available at the Matlab Central File Exchange.

Matlab Central - File Detail - pymex

Valid XHTML 1.0 Strict
Valid CSS!

Last updated 2011-06-15.