The world’s leading publication for data science, AI, and ML professionals.

How to Add an Escape Hatch to Your Python Run in Two Steps

Using decorator functions to create an easy exit to your Python App

Python tips and tricks

Image created by Author | Used Free Content License elements from canva.com
Image created by Author | Used Free Content License elements from canva.com

You’ve got a Python script/app/function that runs on an endless loop, or maybe you’ve got some functionality that requires you to safely exit the program if it takes too long. How can we safely exit the program? Maybe ctrl C, but that’s not always the safest way – and non-technical people might not know that. Perhaps you’ve got a function that initiates ML modelling that could be taking too long.

Here I’ll give you a decorator framework which you can use on any function to add the ability to safely stop the program if you press the specified key. Which in our case will be the "escape" key.

So what are the criteria here?

  • Create a decorator that you can wrap around any function so that if that function takes too long, we can safely stop it with an escape key
Image created by Author | Used Free Content License elements from canva.com
Image created by Author | Used Free Content License elements from canva.com

The Github Repository

I’ve put the framework on a GitHub repository which you can find here:

GitHub – Causb1A/escape-hatch: Escape hatch python repository to complement TDS article

I may refer to aspects of the repository. If you use the repository, start with main.py and debug mode from there. You can find the escape hatch in my_app/api_utils.py

Prerequisite Knowledge

Before going into the details I just want to cover that I use Decorator Functions and a decorator factory to do this. If you’re not sure how these work, please read more on it here:

Decorators in Python

At a very high level, a decorator is a function that takes another function and extends the behaviour of the latter function.

Think of it as a wrapper:

Image created by Author | Used Free Content License elements from canva.com
Image created by Author | Used Free Content License elements from canva.com

You can wrap any function with a decorator, and it will basically execute stuff around the function. So whenever you call a function that’s wrapped with a decorator, it will execute the decorator and the function will execute within the decorator. That’ll make more sense with our example.

Steps

Step 1: Defining the decorator

Create a new module, in the repository, I call this module api_utils.py, I define the decorator function here and call it escape hatch.

The function above is our decorator, we can wrap this around any function. If I start a function wrapped by this decorator, whenever I press the escape key it will halt the program (kill the main thread).

Couple of things to note:

  • line 34 denotes a context manager that listens to any keyboard actions, if one was to happen it will initiate line 26 which halts the program
  • Line 40 is where the executed function happens

Step 2: Using our decorator function

Now how do we use it? Quite simply like so:

Note – If you’re following in the repository this file is in my_app/module_1.py

It’s as simple as above, now whenever you want to use the escape hatch, just simply wrap it like above on line 5 before any function. use @escape_hatch and the function afterwards. The start message and end message are optional.

Function_that_runs_forever() is a function that runs forever, used to test the escape hatch. Let’s test it:

Image created by Author
Image created by Author

I’ve purposely shifted some of the messages to the right so we can clearly see which part is the decorator wrapper.

So what happened?

  1. The escape hatch decorator started, printed out some stuff and it listens to our keyboard to see if we press escape.
  2. Our actual function_that_runs_forever() starts running. This prints Just_Running and will go forever unless I stop it.
  3. I then press the escape key and the decorator stops the function and prints Program terminated by user.

There you go! Functioning escape hatch.

Step 3 EXTRA: Catching KeyboardInterrupt

Sometimes, depending on what your app does, using a keyboard to kill the main thread can sometimes raise a KeyboardInterrupt exception and outputs the traceback. Outputting the traceback may not be something you want. To fix this you can add a try and except which is what I did in main.py of the repository:

Notice in line 11 I catch that exception?

Final Words

Hopefully the above can help you understand decorator functions a bit better and allow you to apply an escape hatch to functions that are prone to running for too long. You can manipulate the decorator to be for different keys or perhaps even something else to initiate the stop. It’s all at your fingertips.

If you’ve enjoyed this article, please leave a clap and a follow for support!

Or if you’re interested in joining the Medium community, here’s a referral link:

Join Medium with my referral link – Adrian Causby

Credits to Marcell Orban for writing the framework with me for our applications.


Related Articles