accessing REPL via pyserial

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
v923z
Posts: 168
Joined: Mon Dec 28, 2015 6:19 pm

accessing REPL via pyserial

Post by v923z » Fri May 04, 2018 7:26 pm

Hi all,

I think, the answer to my question is rather trivial, the snag is, I don't know what it is. In short, I would like to use the REPL from python, meaning that I would like to open the serial port on the PC from python, and then put the instructions on the serial line. This works fine till I enter an instruction that should return something. In such cases, I resorted to an explicit print statement, but that is really not an ideal solution. Here is an example using pyboard.py.

This does not return anything

Code: Select all

python pyboard.py -c '3*3'
while this prints 9, as expected:

Code: Select all

python pyboard.py -c 'print(3*3)'
My question is, whether it is possible to save the print statement. I can easily strip the string of control characters (like Cntr-b or similar), so I don't care, if the return string is "dirty".

Thanks,

Zoltán

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: accessing REPL via pyserial

Post by dhylands » Fri May 04, 2018 7:40 pm

You can use pyboard.py to run a program which saves the text "print(3*3)" into a file. Or you can use rshell (https://github.com/dhylands/rshell) to copy files into and out of the internal filesystem.

If you're using rshell with the pyboard, then the default buffer size is fine. With ESP8266/ESP32 boards, try:

Code: Select all

rshell -a --buffer-size=30 --port /dev/ttyUSBx
(replace the port name as appropriate).

rshell also has a repl command, so you can use it like a terminal program as well as examining/manipulating the files on the filesystem.

v923z
Posts: 168
Joined: Mon Dec 28, 2015 6:19 pm

Re: accessing REPL via pyserial

Post by v923z » Fri May 04, 2018 7:46 pm

Hi Dave,

Thanks for the comments.

At the more fundamental level, the question really is, why pyserial devours the output of REPL, while e.g., screen does not. My problem is not that I can't save the output of print, but why I have to use print in the first place. In other words, is it possible to emulate screen, or putty etc. in python (on the PC) itself, and if the answer lies in the affirmative, how should I go about it?

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: accessing REPL via pyserial

Post by pythoncoder » Sat May 05, 2018 5:14 am

v923z wrote:
Fri May 04, 2018 7:46 pm
...is it possible to emulate screen, or putty etc. in python (on the PC) itself...
Have you seen miniterm.py? This works well on the PC with MicroPython targets.
Peter Hinch
Index to my micropython libraries.

v923z
Posts: 168
Joined: Mon Dec 28, 2015 6:19 pm

Re: accessing REPL via pyserial

Post by v923z » Sat May 05, 2018 4:38 pm

pythoncoder wrote:
Sat May 05, 2018 5:14 am
Have you seen miniterm.py? This works well on the PC with MicroPython targets.
Thanks for the pointer, Peter! This works. Now I've just got to figure out, why ;)

Cheers,

Zoltán

User avatar
fos
Posts: 44
Joined: Sat Feb 18, 2017 3:05 pm
Location: Texas
Contact:

Re: accessing REPL via pyserial

Post by fos » Sat May 05, 2018 6:04 pm

Share when you find out why?

Thanks, fos1

cefn
Posts: 230
Joined: Tue Aug 09, 2016 10:58 am

Re: accessing REPL via pyserial

Post by cefn » Sun May 06, 2018 7:28 am

This reference code for wrapping miniterm might be handy...

https://github.com/vgkits/vanguard/blob ... s/shell.py

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: accessing REPL via pyserial

Post by dhylands » Mon May 07, 2018 4:22 pm

v923z wrote:
Fri May 04, 2018 7:46 pm
Hi Dave,

Thanks for the comments.

At the more fundamental level, the question really is, why pyserial devours the output of REPL, while e.g., screen does not. My problem is not that I can't save the output of print, but why I have to use print in the first place. In other words, is it possible to emulate screen, or putty etc. in python (on the PC) itself, and if the answer lies in the affirmative, how should I go about it?
pyserial reads the data from the serial port. It does not print that data out anywhere. Any of the terminal programs will read data from the serial port and print it to stdout. If you try the python miniterm.py, then you'll see that it does the same thing.

For example, here's a really simple serial terminal written in C, which reads from the serial port and prints the data. Even in C, you need to explicitly print the data:
https://github.com/dhylands/projects/bl ... /sertest.c

Where sertest reads the data from the serial port:
https://github.com/dhylands/projects/bl ... est.c#L352
Where sertest prints the data to stdout:
https://github.com/dhylands/projects/bl ... est.c#L370

v923z
Posts: 168
Joined: Mon Dec 28, 2015 6:19 pm

Re: accessing REPL via pyserial

Post by v923z » Mon May 07, 2018 7:37 pm

dhylands wrote:
Mon May 07, 2018 4:22 pm
pyserial reads the data from the serial port. It does not print that data out anywhere. Any of the terminal programs will read data from the serial port and print it to stdout. If you try the python miniterm.py, then you'll see that it does the same thing.

For example, here's a really simple serial terminal written in C, which reads from the serial port and prints the data. Even in C, you need to explicitly print the data:
https://github.com/dhylands/projects/bl ... /sertest.c

Where sertest reads the data from the serial port:
https://github.com/dhylands/projects/bl ... est.c#L352
Where sertest prints the data to stdout:
https://github.com/dhylands/projects/bl ... est.c#L370
I am afraid, I probably misunderstand you here, so I will just ask for clarification. My problem is not that I need an explicit print statement on the computer side. That's OK. The question is, why I need a print statement on the board? Your examples pertain to the code on the computer, don't they?

If I go back to my original question, the code snippet that I brought up was

Code: Select all

python pyboard.py -c 'print(3*3)'
Here the code (print(3*3)) is running on the board, it just so happens that I pass it through pyboard.py. What I don't understand is this: when I log on to the board by means of screen or putty,

Code: Select all

>>> 3*3
9
>>> print(3*3)
9
>>> 
and I don't see any difference. Yet, the first line yields nothing, if I run it through pyboard. My expectation was that, if on the board two instructions produce the same output, then it should not matter what I do with that output, and it I pipe it through some other piece of code, then I should get the same results. But that is obviously not the case, and this is what bugs me.

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: accessing REPL via pyserial

Post by dhylands » Wed May 09, 2018 4:36 pm

v923z wrote:
Mon May 07, 2018 7:37 pm
If I go back to my original question, the code snippet that I brought up was

Code: Select all

python pyboard.py -c 'print(3*3)'
Here the code (print(3*3)) is running on the board, it just so happens that I pass it through pyboard.py. What I don't understand is this: when I log on to the board by means of screen or putty,

Code: Select all

>>> 3*3
9
>>> print(3*3)
9
>>> 
and I don't see any difference. Yet, the first line yields nothing, if I run it through pyboard. My expectation was that, if on the board two instructions produce the same output, then it should not matter what I do with that output, and it I pipe it through some other piece of code, then I should get the same results. But that is obviously not the case, and this is what bugs me.
In python, when you're inside a script, the statement '3 * 3' is an expression which yields the result 9. Since this isn't assigned to anything, and evaluating the expression doesn't cause any side-effects, this is essentially a no-op.

In the REPL, each statement you execute is evaluated and if the return value from the statement is not equal to None, then the result is printed. Consider the following:

Code: Select all

>>> def foo():
...     print('Hey there')
...     return 42
... 
>>> foo()
Hey there
42
>>> def foo2():
...     print('Another print')
...     return None
... 
>>> foo2()
Another print
>>> def foo3():
...     print('foo3')
... 
>>> foo3()
foo3
>>> def foo4():
...     print('Before 3 * 3')
...     3 * 3
...     print('After 3 * 3')
...     return 42
... 
>>> foo4()
Before 3 * 3
After 3 * 3
42
An function which doesn't return anything winds up returning None

Post Reply