select.poll not working properly with sys.stdin
Port, board and/or hardware
MicroPython v1.24.1 on 2024-11-29; Raspberry Pi Pico with RP2040
MicroPython version
When using sys.stdin with select.poll and calling poll() or ipoll() to wait for available data, only sys.stdin.read(1) returns while sys.stdin.read() blocks.
However, reading only character by character is probably very inefficient and blows up code additionally.
Reproduction
import sys, select
import sys, select
p = select.poll()
p.register(sys.stdin, select.POLLIN)
while True:
for o, _ in p.ipoll():
if o is sys.stdin:
read = sys.stdin.read()
print('read', read)
Expected behaviour
sys.stdin.read() should immediately return when sending data to the serial interface on the PC the Pico is connected to.
Observed behaviour
sys.stdin.read() still blocks.
The same behavior when using sys.stdin.buffer instead of sys.stdin.
The code works when using sys.stdin.read(1) instead of sys.stdin.read()
Additional Information
No, I've provided everything above.
Code of Conduct
Yes, I agree
sys.stdio: add support for ioctl and make sys.stdin.buffer.read non-blocking
This PR allows to poll sys.stdin for readability, and also makes sys.stdin.buffer.read non-blocking (but keeps sys.stdin.read blocking as it was before). A port must provide mp_hal_stdin_rx_avail() for this to work (this function is only implemented on esp8266 for now).
Testing of polling can be done with:
import sys, select
while True:
res = select.select([sys.stdin.buffer], [], [])
data = sys.stdin.buffer.read(1)
print('got', data)
if data == b'q':
break
Testing of non-blocking read can be done with (enter chars while it's sleeping):
import time, sys
time.sleep(3); print(sys.stdin.buffer.read(4)
See issue #4849 for background.