2

Suppose that you have the following .m script:

% foo.m
function foo = run()
    disp('Hello!!');
    foo = 1;
end

Now, you execute foo.m from python with:

import matlab.engine
eng = matlab.engine.start_matlab()
py_foo = eng.foo()

This code will set py_foo = 1 AND will display the output Hello. How do I suppress matlab output?

Neb
  • 2,270
  • 1
  • 12
  • 22
  • 1
    Put a semicolon after `foo = 1;` in the matlab script? – FHTMitchell Apr 03 '18 at 12:31
  • No. It was a typo that after `foo = 1` I missed the semicolon. I mean, the output I see comes from `disp('foo')` but I don't want it. I'll modify my question to make it less confusing. – Neb Apr 03 '18 at 12:33
  • 2
    Maybe this can help you: [Silence the stdout of a function in Python without trashing sys.stdout and restoring each function call](https://stackoverflow.com/questions/2828953/silence-the-stdout-of-a-function-in-python-without-trashing-sys-stdout-and-resto) – Georgy Apr 03 '18 at 12:35
  • @Georgy yes, can work. Not sure since redirection is only for python system output/error. Let OP try that :) – Jean-François Fabre Apr 03 '18 at 12:38
  • Thank @Georgy. I'll let you know if i solved that way. – Neb Apr 03 '18 at 12:40
  • 1
    please let us know so we can close the question as a duplicate (without downvotes :)) – Jean-François Fabre Apr 03 '18 at 12:41
  • Unfortunately, it doesn't work. – Neb Apr 03 '18 at 12:54
  • I found the solution. I just needed to specify the value for the `stdout` argument in the function call. In this case, i can solve with: `eng.foo(stdout=io.stringIO())` – Neb Apr 03 '18 at 13:14
  • 3
    It will be cool if you move your comment to an answer and self-accept it. That can be valuable for future users. – Anton Menshov Apr 03 '18 at 13:24
  • @Anton. You're right. I've provided my anwer and I've expanded it a bit. Hope it helps :) – Neb Apr 03 '18 at 17:20

1 Answers1

2

I answer my question.

I didn't read carefully the matlab documentation about the Python API. Following the instruction at this page, the correct answer to my question is:

import matlab.engine
import io

eng = matlab.engine.start_matlab(stdout=io.StringIO())
py_foo = eng.foo()

Out:

// no output! :D

Just in case you are using exec() (and be very sure about user inputs in this case), remember to import io inside the string passed to exec(), i.e.:

import matlab.engine
import io // this is useless!!

eng = matlab.engine.start_matlab()
str = "import io;eng.foo(stdout=io.stringIO())" // put it here
loc = {}
exec(str, {"eng" : eng}, loc)
py_foo = loc["foo"]
Neb
  • 2,270
  • 1
  • 12
  • 22
  • 1
    This answer seems outdated (or plain wrong). `start_matlab` only accepts `async` and `background` as kwargs (I'm using version 2020a). The link that @Neb provides shows the correct usage, i.e. supply the kwargs `stdout` and `stderr` for every call to the engine. There doesn't seem to be a proper way to disable output alltogether. – mkl Feb 10 '21 at 13:20
  • @mkl At the time I posted this answer (Apr '18), this solution worked with Matlab '18 and the corresponding matlab engine. I cannot guarantee it will work on any future version and I do not think this is a valid reason to downvote. – Neb Feb 11 '21 at 18:57