Capturing stdout from exec()

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
chrisgp
Posts: 41
Joined: Fri Apr 01, 2016 5:29 pm

Capturing stdout from exec()

Post by chrisgp » Fri Apr 01, 2016 5:37 pm

Hello,

Any tips on how I can go about capturing stdout? I want to exec() something and capture the output to a buffer but sys.stdout doesn't seem replaceable in MicroPython on the PyBoard

Based on examples such as: https://stackoverflow.com/questions/121 ... ing-buffer

>>> import sys
>>> from _io import StringIO
>>> buffer = StringIO()
>>> sys.stdout = buffer
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'stdout'

wendlers
Posts: 47
Joined: Wed Mar 16, 2016 10:07 pm

Re: Capturing stdout from exec()

Post by wendlers » Sat Apr 02, 2016 7:53 pm

Hi,

if the MicroPython platform you are using has support for os.dupterm, you could try the following (kind of a work-around I would say).

Add a module/object that offers read/write methods - e.g. by adding module myio.py like so:

Code: Select all

data = b''

def clear():
    global data
    data = b''

def read(n=-1):
    return 0

def write(b):
    global data
    data += b
    return len(b)
Now, somewhere else (e.g. in main.py):

Code: Select all

import os
import myio
os.dupterm(myio)
myio.clear()
exec("print('hello world')")
# now, access result of "exec" trough "myio.data"
But it should be noted, that if a REPL is used, myio.data will contain everything entered (and outputed) on the REPL!

chrisgp
Posts: 41
Joined: Fri Apr 01, 2016 5:29 pm

Re: Capturing stdout from exec()

Post by chrisgp » Sun Apr 03, 2016 7:16 pm

Thanks, at first that seemed promising but as far as I can tell due to limitations on the os.dupterm method the PyBoard implementation isn't going to support it at least.

The UNIX build I run on my mac doesn't have dupterm in the uos module and doesn't have an os module. For the PyBoard build it looks like dupterm explicitly expects the object passed in to be of type pyb.UART.

[code]
>>> myio = MyIO()
>>> os.dupterm(myio)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: need a UART object}[/code]
[/code]
If I check the repository it seems like this isn't too surprising based on the comments: https://github.com/micropython/micropyt ... uos.c#L378
[code]
// Get or set the UART object that the REPL is repeated on.
// TODO should accept any object with read/write methods.
STATIC mp_obj_t os_dupterm(mp_uint_t n_args, const mp_obj_t *args)[/code]

I tried various ways to get around it like subclassing pyb.UART, changing the class of my MyIO type after instantation, and attempting to override the write method of an instance of UART but ran into various barriers with each of them.

wendlers
Posts: 47
Joined: Wed Mar 16, 2016 10:07 pm

Re: Capturing stdout from exec()

Post by wendlers » Mon Apr 04, 2016 8:03 pm

Interresting. I only tried on ESP port so far which uses in general the same code as the unix variant regarding the term object.

cpr
Posts: 11
Joined: Thu Mar 03, 2016 4:56 pm
Location: LDK, OWL @ .de

Re: Capturing stdout from exec()

Post by cpr » Sun Sep 25, 2016 8:50 am

Funny, I came here the exact same way as the OP: I want to remote-execute code on an ESP8266 by means of pyboard.py wrappers (e.g. mpfshell).

My first, randomly chosen, sample was to get the output of esp.check_fw() which not just does return True/False but also prints out 'stuff'.
So over the serial line I do get a lot of "noise", not just the return value.

I guess I will implement some 'protocol' with start-of-message and end-of-message markers. Maybe wrap the message I am interested in with JSON markup.

Post Reply