Understanding Python Context-Managers for Absolute Beginners

Understand the WITH statement with lightsabers

Understanding Python Context-Managers for Absolute Beginners
We’ll code our own lightsaber (image by Venti Views on Unsplash)

You are definitely familiar with context managers—they use the with statement:with open('somefile.text', 'r') as file:
  data = file.read()

In this article we’ll focus on what happens when we call a context manager:

  • What is a context manager?
  • How does it work?
  • What are its advantages?
  • Creating your own context manager

Let’s code!


Before we take on some real-life example of code using the context manager we’ll understand the inner workings with a clear example: imagining we’re coding a lightsaber.

Understanding Python decorators: six levels of decorators from beginner to expert
How decorators work, when to use them and 6 examples in increasingly complexity

Setup: coding the lightsaber

I’m pretty sure everyone is familiar with those: the super-dangerous, red-hot plasma blade that slices through everything it touches. Before we use them to stab or slash we need to activate it and after we’re done using it we should always de-activate this insanely dangerous piece of equipment. In code:

Nothing too special: we keep track of two attributes: color and active. In this example color is pretty decorative, active however is pretty important since we can only use the slash() and stab() methods if we’ve activated our saber. We have two functions that control the state: turn_on() and turn_off().

The way you’d use this code is like this:

This code is pretty high-maintenance; we mustn’t forget to turn on our lightsaber because it will throw an exception otherwise. Also we need to call the turn_off() method every time. How can we make this code easier to use?

Multi-tasking in Python: Speed up your program 10x by executing things simultaneously
Step-by-step guide to apply threads and processes to speed up your code

When to use a context manager?

In case of our lightsaber we always need to turn on the saber before we can do anything with it. Also we always need to turn if off because otherwise we cannot holster it and also energy prices are pretty high nowadays.

Remember that for turning the saber on and off we need to call the turn_on() and turn_off() methods. The lightsaber is an ideal use-case for the context manager since we need to perform an action every time before and/or after we use it.


Updating the lightsaber with a context manager

We’ll add two special ‘dunder-methods’ to our LightSaber class. Dunder-methods (double-underscore-methods) override functionality for built-in functions for custom classes. You might already know one: the __init__() method!

We’ll add a __enter__ and __exit__ method so our Lightsaber class now looks like this:

As you’ll see the functions for turning the saber on and off are called in these enter and exit methods. We can now use the class like this:

As soon as we hit the with statement we enter the __enter__ method which will turn on our lightsaber. Then we can slash and stab all we want. Once we exit the block of code the __exit__ method is called turns off our lightsaber.

The advantages are clear:

  • Our code is much more concise.
  • Our code is much easier to read.
  • It automatically turns on when we want to start slashing and stabbing.
  • It automatically turns off when we’re done murdering, preventing many injuries trying to holster it.
Simple trick to work with relative paths in Python
Calculate the file path at runtime with ease

Context managers in the wild

The lightsaber is a bit of a toy-example but there are many occasions where a context manager is used. The example below details Python’s built-in functions for reading a file. The default way looks like this:file = open('somefile.txt')
content = file.read()
file.close()

If we don’t call file.close() in the example above then our file will be occupied by our script. This means that no other processes can access it. Let’s use the context-manager:with open('somefile.txt') as file:
   content = file.read()

The code above will close the file automatically. Also it is much easier to read.

Another example lies in database-connections. After we create a connection to a database and use it to read/write data to that database, we mustn’t forget to commit the data and close the connection. The regular implementation:cursor = conn.cursor()
cursor.execute("SELECT * FROM sometable")
cursor.close()

Thankfully many packages implement a context manager like this:with dbconnection.connect() as con:
   result = con.execute("SELECT * FROM sometable")

The code above makes sure that the connection is closed as soon as we’re done with it. At the moment I’m in the process of creating a guide for connecting Python to a database; follow me if you are interested!

Create a fast auto-documented, maintainable and easy-to-use Python API in 5 lines of code with…
Perfect for (unexperienced) developers who just need a complete, working, fast and secure API

Conclusion

In this article we’ve covered the basics of context managers in Python and I hope to have shown you when and how to use one.

If you have any tips on improving this article; please comment! In the meantime, check out my other articles on all kinds of programming-related topics like these:

Happy coding!

— Mike

P.S: like what I’m doing? Follow me!

Join Medium with my referral link — Mike Huls
As a Medium member, a portion of your membership fee goes to writers you read, and you get full access to every story…