DEV Community

Cover image for Exceptions To The Rescue in Micropython
Kevin Asaria
Kevin Asaria

Posted on

Exceptions To The Rescue in Micropython

I have never really been a fan of how exceptions look like in code. Mostly because of the nesting it causes , it is already giving me flashbacks of callback hell. And this has made me use them less in my code, or even not think about using them which comes back to bite me from time to time.

However, since I have been making an embedded system using Micropython I have come to find a big appreciation for them. Having come from the backend world, I actually never experienced my whole app crashing because of an exception occurring. Over there, the server spins a new thread of execution whenever a request is received and the thread crashes on its own and does not crash the whole program.

Contrast this with embedded system development, if an exception occurs your whole application crashes. And this is unexceptable if you want your system to be resilient and available 24/7. And here is where our hero the try and except block comes along. Saving you from the danger of you code crashing and you being in the dark about it.

What I decided to do was to wrap the setup and loop part of my code in exceptions as shown below


import blah_blah_blah

try:
  setup()

except Exception as e:
  do_something()

while True:
  try:
    app()
  except Exception as e:
    handle_loop_exception()
Enter fullscreen mode Exit fullscreen mode

Of course you can be more specific in your exceptions and structure. I think this is what they call failing gracefully and with style if you wish.

Some of the things that resulted in exceptions that I had not forseen include:

Index out of range exception

Sometimes you expect a list to have N elements but it has fewer and you expect a certain index to have the value you want but now it is nowhere to be found.

   data = some_string.split(',')
   answer = data[4]
Enter fullscreen mode Exit fullscreen mode

Like in the above , we expect that if we split the string using a comma, it will at least 5 elements but that is not always the case and you need to deal with such an issue at runtime

KeyError Exception

In this case you are accessing a non existant key from a dictionary. using the syntax

a = my_dict['alien']
Enter fullscreen mode Exit fullscreen mode

instead of this syntax, I would suggest using

a = my_dict.get('alien')
Enter fullscreen mode Exit fullscreen mode

In which case you would get None if the key is not in the dictionary.
But what if you have a nested dictionary. Being lazy I have left that as an exercise to the reader

Memory Error

I am guilty of assuming sometimes that I am still writing a program that will run on a server or pc. I have encountered this error when I have tried to read and manipulate some long log files. And you might lose data from the file that you are trying to write to if this exception occurs

   with open('file.txt', 'w') as f:
      f.write('here I am')
Enter fullscreen mode Exit fullscreen mode

In the above example if there is not enough memory to allocate for the file content and exception would occur and you would even lose your file content

Threads and Locks

I'll finish of with where I really got myself into trouble when I was not using exceptions, that is, when I had acquired a lock and an exception occured before I released it causing a deadlock. Without logs I wonder if I would have ever gotten myself out of that problem. But the lesson was clear, just wrap the operations in between the acquiring and release of a lock in a try except block as below

lock.acquire()
try:
    # Critical section
    print("Shared resource accessed")
finally:
    lock.release()

Enter fullscreen mode Exit fullscreen mode

NB: You can deal with exceptions where they occur and not just 'globally' as I have shown, this is just to catch any exceptions that you might have forgotten about.

Thank your for your time and hope this helps somewhere.

Top comments (0)