pybricks / support

Pybricks support and general discussion

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Bug] using f'format strings in tight loop blocks and triggers watchdog timer

BertLindeman opened this issue · comments

commented

Describe the bug
Program is a tight loop printing f-strings. Within seconds the hub does a shutdown (somehow)
The display animation is no longer smooth but has large hickups.

Might this be related to #436 ?

To reproduce
Steps to reproduce the behavior:

  • connect the hub to USB for power
  1. Running in code.pybricks.com or beta
  2. Current setup is RobotInventor at 3.5.0 and SpikePrime at build 3380 (BT-button change)
  3. connect to the hub
  4. start the program (see below) via the app or website
  5. stop the program via the app and disconnect the hub
  6. stop the program by long-press on the hub button
  7. start the hub and run the program again (button press) but do not connect to the app
  8. a bit of patience (seconds) and see the hub goes OFF

Aditional info
Connected the hub before the test to USB to keep the power on.
After the crash connect to the hub and go to the REPL.
Showed:

>>> hub.system.reset_reason()
2
>>> 

Expected behavior
You'd expect the program to just keep running and not to power-off.

Screenshots
There is a saying that a picture is worth a 1000 words. Screenshots really help to identify and solve problems.

test program for this issue
# issues try_movehub_on_prime_6
# start this and while running disconnect with the app
# stop the hub to save the current program
# restart the hub (if build 3380 installed press the BT button -> red)
# start the program with the button, and
# within seconds the running square stops and the hub shutsdown


from pybricks.hubs import PrimeHub
from pybricks.tools import wait

HUB = PrimeHub()

# Initialize variables.
color_list = ["", "", "", "", "", "", ""]

_rand = HUB.battery.current() + HUB.battery.voltage()
# _rand = 123
INDEX = 4
A = 0
B = 5


def main2():
    while True:
        print(f'pre _rand {_rand:>5} A {A:>2} B {B:>2}', end=" ")
        print(f'_rand {_rand:>5} A {A:>2} B {B:>2}')
        print(f'INDEX {INDEX:>3} color_list[{INDEX}] {color_list[INDEX]}')
        # wait(1)  # with 1ms second wait: no problem
        wait(0.75)  # this wait is not enough to prevent the error


main2()

Good find! When not connected, it is supposed to ignore printed output but that clearly isn't happening.

Did you try this on any other hub?

commented

Did you try this on any other hub?

Up to now only the Spike and Inventor. Will "do" others.

More minimal program and method below.

Run this on SPIKE Prime and press the disconnect button in Pybricks Code. No need to restart anything.

while True:
    print(f'hello - hello - hello - hello - hello - hello - hello')
    print(f'hello - hello - hello - hello - hello - hello - hello')

The hub doesn't quite crash all the way, but the animation still visibly stutters. Just for less than it needs for the watchdog timer to trigger.

Yet this is OK. So I guess we'll have to have a look at the format-string source code:

while True:
    print('hello - hello - hello - hello - hello - hello - hello')
    print('hello - hello - hello - hello - hello - hello - hello')
commented

This one stutters:

while True:
    print(f'{"hello":>10} -{"hello":>10} {"hello":>10} {"hello":>10} {"hello":>10}')
    print(f'{"hello":>10} -{"hello":>10} {"hello":>10} {"hello":>10} {"hello":>10}')

    print(f'{"hello":>10} -{"hello":>10} {"hello":>10} {"hello":>10} {"hello":>10}')
    print(f'{"hello":>10} -{"hello":>10} {"hello":>10} {"hello":>10} {"hello":>10}')

Yes, any long f'string' seems to be an issue. Normal strings seem fine.

commented

Did you try this on any other hub?

How to "see" the stutter the other hubs?
I have the Move / City / 2 Technic hubs running with 8 of these print lines.
The inventor and prime hub stop automagically but the others run happily on.
Maybe the blue light is a bit more step by step. But now very clear.

Thanks for having a look! Since it seems to be specifically related to these format strings, I think it's OK to stick to just the primehub for now to keep it simple.

Thanks for bringing it to our attention. I haven't used these f-strings much in Pybricks for some reason.

commented

Thanks for having a look! Since it seems to be specifically related to these format strings, I think it's OK to stick to just the primehub for now to keep it simple.

Thanks for bringing it to our attention. I haven't used these f-strings much in Pybricks for some reason.

I like the f-strings more and more. Just getting to know the formatting characters.

BTW this was the issue I found while testing the BT-on/off change in build 3380.

commented

You know me, I keep fiddling 😄

Idea was does the f-string pose the problem or the print doing the formatting.

This snippet:

formatted1 = f'{"hello" * 3:>20} - {"wow"[:2]:>10} {"hello":>10} {"hello":>10} {"hello":>10}'
print(type(formatted1))
formatted2 = f'{formatted1[:10]:>20}'

while True:
    formatted2 = f'{formatted1[:10]:>20}'
    print(type(formatted1), formatted1)
    print(formatted2)
    print(type(formatted1), formatted1)

with an f-string in the loop makes the animation stutter.

The same program but the formatting commented out within the loop does not stutter:

formatted1 = f'{"hello" * 3:>20} - {"wow"[:2]:>10} {"hello":>10} {"hello":>10} {"hello":>10}'
print(type(formatted1))
formatted2 = f'{formatted1[:10]:>20}'

while True:
    # formatted2 = f'{formatted1[:10]:>20}'
    print(type(formatted1), formatted1)
    print(formatted2)
    print(type(formatted1), formatted1)

The watchdog is not triggered.

The 3 print commands are needed to see the stutter.

[EDIT]
Without the print statements in the loop, but with f-strings "that do formatting on slices" the running display animation is skipping frames, in my terms it stutters.
With SLICE = False the normal display animation.

The boolean SLICE determines which loop runs: f-strings with or without slices
# SLICE = False  # normal animation
SLICE = True  # animation skips frames; my term: it stutters

if SLICE:
    while True:  # loop with only f-string formatting and slices
        formatted1 = f'{"hello?"[:-1] * 3:>20} - {"wow"[:2]:>10} {"hello"[:4]:>10} {"hello":>10} {"hello":>10}'
        formatted2 = f'{formatted1[6:]:<20}'
else:
    while True:  # loop with only f-string formatting and NO slices
        formatted1 = f'{"hello" * 3:>20} - {"wow":>10} {"hello":>10} {"hello":>10} {"hello":>10}'
        formatted2 = f'{formatted1:<20}'
Movies:
SLICE_False_connected.mp4
SLICE_False_not_connected.mp4
SLICE_True_connected.mp4
SLICE_True_not_connected.mp4