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'
Capturing stdout from exec()
Re: Capturing stdout from exec()
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:
Now, somewhere else (e.g. in main.py):
But it should be noted, that if a REPL is used, myio.data will contain everything entered (and outputed) on the REPL!
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)
Code: Select all
import os
import myio
os.dupterm(myio)
myio.clear()
exec("print('hello world')")
# now, access result of "exec" trough "myio.data"
Re: Capturing stdout from exec()
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.
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.
Re: Capturing stdout from exec()
Interresting. I only tried on ESP port so far which uses in general the same code as the unix variant regarding the term object.
Re: Capturing stdout from exec()
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.
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.