Page 1 of 2

accessing REPL via pyserial

Posted: Fri May 04, 2018 7:26 pm
by v923z
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

Re: accessing REPL via pyserial

Posted: Fri May 04, 2018 7:40 pm
by dhylands
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.

Re: accessing REPL via pyserial

Posted: Fri May 04, 2018 7:46 pm
by v923z
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?

Re: accessing REPL via pyserial

Posted: Sat May 05, 2018 5:14 am
by pythoncoder
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.

Re: accessing REPL via pyserial

Posted: Sat May 05, 2018 4:38 pm
by v923z
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

Re: accessing REPL via pyserial

Posted: Sat May 05, 2018 6:04 pm
by fos
Share when you find out why?

Thanks, fos1

Re: accessing REPL via pyserial

Posted: Sun May 06, 2018 7:28 am
by cefn
This reference code for wrapping miniterm might be handy...

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

Re: accessing REPL via pyserial

Posted: Mon May 07, 2018 4:22 pm
by dhylands
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

Re: accessing REPL via pyserial

Posted: Mon May 07, 2018 7:37 pm
by v923z
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.

Re: accessing REPL via pyserial

Posted: Wed May 09, 2018 4:36 pm
by dhylands
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