I can’t interact with micropython by Popen

Discussion about programs, libraries and tools that work with MicroPython. Mostly these are provided by a third party.
Target audience: All users and developers of MicroPython.
rockindy
Posts: 4
Joined: Fri Apr 24, 2020 2:56 am

I can’t interact with micropython by Popen

Post by rockindy » Fri Apr 24, 2020 3:18 am

Hi,

I tried to use Popen of python2/3 to interact with micropyton unix port, but will be blocked by proc.stdout.readline() function:

Code: Select all

proc = subprocess.Popen(['./micropython', '-i'],
                        stdin=subprocess.PIPE,
                        stdout=subprocess.PIPE,
                        stderr=subprocess.PIPE)
proc.stdin.write(b'2+2\n')
proc.stdin.flush()
proc.stdout.readline()
Dose anyone has any idea?
Thanks.

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

Re: I can’t interact with micropython by Popen

Post by pythoncoder » Fri Apr 24, 2020 5:26 am

MicroPython is primarily intended to run on microcontrollers where there is no underlying OS. A lot of CPython's functionality assumes an OS and is unsupported.
Peter Hinch

stijn
Posts: 454
Joined: Thu Apr 24, 2014 9:13 am

Re: I can’t interact with micropython by Popen

Post by stijn » Fri Apr 24, 2020 7:11 am

IIRC there is (or was) a way to do this: in the past I've played around with a Jupyter kernel for the unix and windows ports. Don't remember which one though, but in my memory it used Popen or pexpect.ReplWrapper or something like that.

Still, question is: what do you really want to do? Because the code you show could be done using subprocess.check_output or so.

Christian Walther
Posts: 105
Joined: Fri Aug 19, 2016 11:55 am

Re: I can’t interact with micropython by Popen

Post by Christian Walther » Fri Apr 24, 2020 7:17 am

This is CPython.

Apparently micropython does not run the REPL when stdin is not from a terminal, which means that
  • input is only compiled at EOF, not line-wise,
  • you need to use print() to see output.
This works for me:

Code: Select all

>>> proc = subprocess.Popen(['./micropython', '-i'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> proc.stdin.write(b'print(2+2)\n')
11
>>> proc.stdin.close()
>>> proc.stdout.read()
b'4\n'
>>> proc.stderr.read()
b''

rockindy
Posts: 4
Joined: Fri Apr 24, 2020 2:56 am

Re: I can’t interact with micropython by Popen

Post by rockindy » Mon Apr 27, 2020 3:52 am

Hi,

Thanks for your replies.
I want to let user interacts with MicroPython REPL via gui widget, so I need to pipe the stdin/stdout.
@Christian Walther your way works but can only write the stdin once.

Finally I found a way to do it.
For whom encountered the same problem, you can modify the main.c of unix port to solve it:

Code: Select all

--- a/ports/unix/main.c
+++ b/ports/unix/main.c
@@ -657,7 +657,8 @@ MP_NOINLINE int main_(int argc, char **argv) {
         inspect = true;
     }
     if (ret == NOTHING_EXECUTED || inspect) {
-        if (isatty(0)) {
+        if (1) {
             prompt_read_history();
             ret = do_repl();
             prompt_write_history();

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

Re: I can’t interact with micropython by Popen

Post by dhylands » Mon Apr 27, 2020 2:34 pm

The way that python and bash does it is to provide a -i or --interactive option which tells it to stick around and do interactive things.

Otherwise if you just wanted to run a script with redirected input it would print a prompt and try to listen to stdin which wouldn't be the intended behaviour.

So changing it to be "if isatty(stdin) || -i flag was specified" would be a solution which you would likely get merged.

Christian Walther
Posts: 105
Joined: Fri Aug 19, 2016 11:55 am

Re: I can’t interact with micropython by Popen

Post by Christian Walther » Mon Apr 27, 2020 5:33 pm

And "-i flag was specified" is exactly the variable inspect used one line above, so the changed line is

Code: Select all

if (isatty(0) || inspect) {
You’ll probably also want to adjust the print_help() text. (CPython’s says “forces a prompt even if stdin does not appear to be a terminal”.)

rockindy
Posts: 4
Joined: Fri Apr 24, 2020 2:56 am

Re: I can’t interact with micropython by Popen

Post by rockindy » Tue Apr 28, 2020 3:05 am

In the current code, once you redirect stdin, it won't call do_repl().

And I don't know how to tell the redirection is from '<' or from Popen.

My suggestion is once you set -i flag, it will always call do_repl().

And if you want to run script from a file, just use '<' without -i flag.

Christian Walther
Posts: 105
Joined: Fri Aug 19, 2016 11:55 am

Re: I can’t interact with micropython by Popen

Post by Christian Walther » Tue Apr 28, 2020 1:12 pm

rockindy wrote:
Tue Apr 28, 2020 3:05 am
And I don't know how to tell the redirection is from '<' or from Popen.
Why would you need to?
My suggestion is once you set -i flag, it will always call do_repl().
That much is common between dhylands’ solution and yours. What’s different is what happens when you don’t set the -i flag.
And if you want to run script from a file, just use '<' without -i flag.
That’s what works in dhylands’ solution but not in yours.

(At least that’s my understanding just from reading the code, I haven’t actually tested it.)

(You may be talking past each other with respect to whether you are talking about “micropython script.py < inputfile” or “micropython < script.py”.)

rockindy
Posts: 4
Joined: Fri Apr 24, 2020 2:56 am

Re: I can’t interact with micropython by Popen

Post by rockindy » Wed Apr 29, 2020 6:38 am

Sorry, I think I misunderstood dhylands' post.
The correct understanding is:

Code: Select all

     if (ret == NOTHING_EXECUTED || inspect) {
-        if (isatty(0)) {
+        if (isatty(0) || inspect) {
             prompt_read_history();
With this patch, it should work as excepted.
Thank you @dhylands and @Christian Walther.

Post Reply