Debugging in Python - ($%@#&^%$#!)

I’m working on my “multiboot project” and I’m messing around with a startup script.

Viz:

#------------------------------------
# Main routine entry point is here
#------------------------------------

if __name__ == "__main__":
    #Shaking Charlie's head to indicate startup
    center_head()
    sleep(0.25)
    shake_head()
    sleep(0.25)
    logging.info("Ready to go!\n")
    
    # check to see which kernel is being run
    os_version = os.popen('uname -m').read()

    print("os_version is", os_version)
    if os_version == "aarch64":
        print("64 bit O/S")
        gopigo3_robot.left_eye_color = (0, 0, 65)  # set eyes blue if 64 bit
        gopigo3_robot.right_eye_color = (0, 0, 65)
    else:
        print("32 bit O/S")
        gopigo3_robot.left_eye_color = (0, 65, 0)  # otherwise, set to green if 32 bit
        gopigo3_robot.right_eye_color = (0, 65, 0)

    gopigo3_robot.open_eyes()  # enable eyes.
    sys.exit(0)

This is just the relevant section. The entire, (working), script is at the bottom of this posting.

What this script is supposed to do is:

  1. Move Charlie’s head around and then re-center it in both axes to face forward to indicate that boot-up is complete.  (The script’s original function.)

  2. Display the “bitness” of the running kernel by turning Dex’s eyes either green, (32 bit kernel), or blue, (64 bit kernel).

==================

It is important to note that, when running the 64 bit kernel, “uname -m” returns (what appears to be) “aarch64” within a terminal window.

So, I run the script and get all kinds of unholy errors - as expected.

For example:
If you want to run a shell command in Python, there’s a handy module, (os), that you import and then " os.system('myCmd')" runs whatever shell command you want. In my case os.system('uname -m') returns the architecture of the system running, either “aarch64” or “armv7l” depending on the bitness of the kernel running.

OK, I’m in!  Works for me. . .

So, I start modifying my script and I do the obvious:
os_version = os.system('uname -m') (The single quotes are important around the “uname -m”, otherwise it expects a variable.)

No error, (at least not there. . .), but no joy.

Turns out that what “os.system()” returns is the exit status of the command run.  Which, though handy, isn’t what I expected.  So, silly me, I’ve been returning “0” to my comparison.  (errrr!)

It turns out if you want to get the actual result of the command, (as opposed to its return code), you have to do something different - a totally unholy, (and un-obvious), os_version = os.popen('uname -m').read().

Don’t ask me where that came from.  I have no clue whatsoever.  However, it returns what I want, a string containing either “aarch64” or “armv7l” depending on what kernel is running.

So, onward and upward!  I continue coding. . . .

# check to see which kernel is being run
    os_version = os.popen('uname -m').read()

    print("os_version is", os_version)
    if os_version == "aarch64":
        gopigo3_robot.left_eye_color = (0, 0, 65)  # set eyes blue if 64 bit
        gopigo3_robot.right_eye_color = (0, 0, 65)
    else:
        gopigo3_robot.left_eye_color = (0, 65, 0)  # otherwise, set to green if 32 bit
        gopigo3_robot.right_eye_color = (0, 65, 0)

    gopigo3_robot.open_eyes()  # enable eyes.

So, I run it.

The expectation is that if the uname command returns “aarch64”, Dex’s eyes will turn blue and if it returns anything else, they’ll turn green.

What happens?  Just guess. . .  And if you guessed that I had a working program, you’d be wrong!

The print returns “os_version is aarch64” and yet the lights turn green.

Hmmm. . . .

Maybe the “if” is hitting both conditions?  So, I add print statements.

    if os_version == "aarch64\n":
        print("64 bit O/S")  # <== added this statement
        gopigo3_robot.left_eye_color = (0, 0, 65)  # set eyes blue if 64 bit
        gopigo3_robot.right_eye_color = (0, 0, 65)
    else:
        print("32 bit O/S") # <== and this one to see who is who
        gopigo3_robot.left_eye_color = (0, 65, 0)  # otherwise, set to green if 32 bit
        gopigo3_robot.right_eye_color = (0, 65, 0)

If it’s hitting both, I’ll get both print statements.

Try again.

It returns
“os_version is aarch64”
“32 bit O/S”
. . .and the lights turn green (again).

Hmmm. . . It’s failing the test for the 64 bit O/S, yet I know I’m running the 64 bit O/S as uname -m returns aarch64.

Did I misspell it?  (I had no end of trouble with the os command until I finally noticed I misspelled “uname”.)

Nope.

Tried a bunch of things that accomplished nothing.  What IS obvious is that what I think I’m getting, and what I am ACTUALLY getting are two different things.  But they look the same, what’s up?

In desperation, I decide to punt and try the “debugger” in Thonny.


 

And so I run it, selecting “over”, (keep going), each step of the way.

And as I do this, the “variables” pane keeps track of what’s happening, just as I expected. . .


 

. . . until I get to the point where the “uname -m” command is executed. . .


 

And there, in all its glory, is my variable’s value. . .  So, what got returned - an “aarch64” as I expected?  NO!

The [censored!!] thing returns “aarch64\n” - with a line-ending character!

Of course, everything makes sense now - “aarch64” does NOT logically equal “aarch64\n” and it always fails.  (Darned non-printing characters!)

The obvious fix, adding the “\n” solves the problem.

And here’s the complete, (working), script for those interested. . .

startup.txt (3.5 KB)

Just in case you were interested, here’s a picture of Charlie running GoPiGo O/S 3.0, with the 64 bit experimental kernel running.  (blue lights)


 

His head was facing forward, but he just can’t help smiling for the camera. . . :wink:

1 Like

also works:

import platform

os_version = platform.machine()

returns just the aarch64 or armv7l

2 Likes

Cool beanies!

I never knew that.  Where did you get that from?  Does it also come back with the line-ending?

Thanks!

1 Like

Good detective work. Things like that can be really hard to track down since they are literally invisible for the most part.
/K

2 Likes