micropython / micropython

MicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems
https://micropython.org
Other
19.46k stars 7.77k forks source link

mpremote: Writing fails when using mount and using multibyte characters. #13055

Open sebromero opened 12 months ago

sebromero commented 12 months ago

I'm on MicroPython v1.21.0 on 2023-10-06; PORTENTA with STM32H747 The following script runs fine when executing it on the board e.g. mpremote connect id:3871345 run ./examples/demo.py

with open("foo.txt", 'w', encoding='utf-8') as file:
    file.write("🔢 Data" + '\n')
    file.write("🔢 Data" + '\n')

with open("foo.txt", 'r', encoding='utf-8') as file:
    data = file.read()
    print(data)

It correctly prints

🔢 Data
🔢 Data

However, when running it after mounting the current directory, it fails. e.g. mpremote connect id:387134 mount . run ./examples/demo.py

It prints

Local directory . is mounted at /remote
ta
ta
🔢 Da🔢 Da

Please note that the ta output is created by the write() function which shouldn't produce any output to the console.

If I modify the above example to write the following data, it stalls: file.write("🔢 Data" + '\n' + "🔢 Data")

Looks like an issue with how multi byte characters are handled when using mount.

felixdoerre commented 10 months ago

I think the problem lies here: https://github.com/micropython/micropython/blob/215a982c1469df214b2beda2db5ed8d562040738/tools/mpremote/mpremote/transport_serial.py#L819C11-L819C19 (or in the called wr_bytes method). The string you write, has a length of 6 however it takes 8 bytes to represent. And this confuses the mount-protocol, which now sends 8 bytes of data, after indicating it is 6 bytes long. I believe there is just a ".encode()" missing there. A quick workaround would be to call .encode() on the data yourself. Reading seems to work fine.