How Python has changed from the perspective of the Brood X Cicadas

June 04, 2021
Written by
Sam Agnew
Twilion

Copy of Generic Blog Header 3(6).png

Every 17 years in the Eastern United States, billions of cicadas belonging to a brood called Brood X emerge from their underground burrows. Their last emergence was in 2004, and now in 2021 they are out and about once again.

A lot has changed over the last 17 years for these cicadas to catch up on, including massive updates to the Python programming language. Let's take a look at Python 2.3.4, the version of Python released in May 2004, and see how it differs from how we write Python today to put things in perspective for our buggy friends.

Two cicadas on a leaf

from may_2004 import newest_python_version

Releases for old Python versions are all still available on python.org, including Python 2.3.4, the that the Brood X Cicadas are most familiar with.

On this release archives page there are two tarball source release files, as well as a Windows installer. You can compile these yourself manually, or try out MacPython. Personally I am just going to run the Windows installer in a virtual machine for the sake of convenience even though I am using a Mac.

The Python 2.3.4 Windows installer

After installation, you can open the Python shell to run whatever code you want.

A Python command line shell displaying code for printing "hello"
The icon in my toolbar for the Python 2.3.4 shell

In Python 2.3.4, there are quite a few new features to check out. Let's go through some of them.

A standard Set datatype

The last time Brood X had written Python, they had access to a new data type for sets. They had to manually import the sets module to use these features, but they could do basic set operations such as union and intersection:

>>> import sets
>>> S = sets.Set([1,2,3])
>>> S
Set([1, 2, 3])
>>> 1 in S
True
>>> 0 in S
False
>>> S.add(5)
>>> S.remove(3)
>>> S
Set([1, 2, 5])
>>> S2 = sets.Set([4,5,6])
>>> S.union(S2)
Set([1, 2, 4, 5, 6])
>>> S.intersection(S2)
Set([5])
>>> S1 = sets.Set([1])
>>> S.issuperset(S1)
True
>>> S1.issubset(S2)
False
>>>

Nowadays, this is built into the language. No import necessary.

A Python 3.9.5 shell displaying that there is no module to import named 'sets'

A Boolean type

Prior to Python 2.3, True and False were constants that existed in the language, but they were literally just the integer values of 1 and 0 rather than having their own dedicated type. Now (in 2004), it has been built into the language as a type named bool, which has a constructor that converts any Python value to True or False:

>>> bool(1)
True
>>> bool(0)
False
>>> bool([])
False
>>> bool( (1,) )
True

The goal here was not to add strict type checking to the language, but to make code more clear to read. You can still do gnarly things like treating these values as integers:

>>> True + 1
2
>>> False + 1
1
>>> False * 75
0
>>> True * 75
75

The release notes say that Python will never be that strict, and this statement has remained true til this day.

A Python 3.9.5 shell displaying arithmetic with the True and False values

Extended slices

In Python 2.3, the built-in list, tuple, and string sequence types now support the third step or stride argument. This has existed in the slicing syntax before, but at the request of the Numerical Python developers who use this feature extensively it is now supported by these built-in types.

>>> L = range(10)
>>> L[::2]
[0, 2, 4, 6, 8]
>>> s='abcd'
>>> s[::-1]
'dcba'
>>>

How did Brood X use Python in 2004?

Python development looked a whole lot different the last time Brood X emerged, so let's take a look at how you would write code for some common tasks that are still popular today.

HTTP requests

For making HTTP requests, urllib2 was the way to go in 2004. It doesn't work with HTTPS, but other than that, it gets the job done. As an example, let's use the International Space Station Open Notify API to write some code to get data about the current location of the ISS:

>>> import urllib2
>>> url = 'http://api.open-notify.org/iss-now.json'
>>> req = urllib2.Request(url)
>>> response = urllib2.urlopen(req)
>>> print response.read()
{"message": "success", "timestamp": 1622701465, "iss_position": {"longitude": "7.4903", "latitude": "-46.3285"}}
>>>

Using a newer library like requests, this is a bit more streamlined:

A Python 3.9.5 shell displaying code for making an HTTP request to the ISS Open Notify API

Installing modules

If a Python-loving Cicada wanted to install modules that weren't part of the standard library in 2004, they had to do it using Distutils.

Sometimes, a third party module might come with installation software for your system, but this was often not the case. If an installer didn't exist, you would have to build it from source. Distutils provided a standard way to do this. Most of the time, you would just need to read whatever instructions were included in the README, and run something like the following command:

python setup.py install

The Python Package Index did exist as of 2003, but there was no pip yet.

File I/O

Reading and writing files is one of the most common things developers do in any programming language. In Python, many developers use the with statement to make code for reading/writing files more clean, because it takes care of loose ends and prevents you from forgetting to close the file afterwards.

This keyword wasn't available in the language until 2005, so our Brood X friends would not have been familiar with it. They would still have had to close their files manually, like in the following code sample:

>>> f=open('filename.txt', 'r')
>>> f.read()
'This is the entire file.\n'
>>> f.close()

In 2021 the code for reading from a file is a bit more consolidated:

A Python 3.9.5 shell displaying code for reading from a file

What does Python have now that wasn't around in 2004?

A lot of things have changed since 2004, so our cicada friends have much to catch up on if they're planning on burrowing into some Python. Let's go over a few things that came into being after the last time they emerged to bring them up to speed.

pip

As mentioned earlier, Brood X would have needed to manually install their third party modules with Distutils. Now we have package management software called pip, which connects to the Python Package Index making installing modules a lot easier!

Rather than running setup.py scripts yourself, all you need to do if you wanted to write some code to send text messages for example, is:

pip install twilio

In the span of a few seconds (or however long it takes to install the module) you can have third party tools available at your fingertips. You can even use a virtual environment to make sure different versions of dependencies don't interfere with each other for different projects. The possibilities are endless.

Web development frameworks

There are a variety of frameworks available for making web applications in Python. The most popular of the two are Django and Flask. Brood X just missed Django by one year as it was initially released in 2005, so I'm sure the scope of the features included for building web applications would blow their insectoid minds.

They would also be excited to see just how little code it takes to write a functioning web app with Flask. After running pip install flask, all you need to do is create a file named app.py and add the following code to it:

from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

And there you have a functional "Hello World" web app!

asyncio

If a cicada wanted to perform tasks that weren't synchronous back in 2004, they would have to use threading. But now asyncio is a part of Python's standard library, which enables developers to write asynchronous code for all sorts of scenarios.

According to this detailed tutorial, two of the primary properties of asynchronicity in code are:

  • Asynchronous routines are able to “pause” while waiting on their ultimate result to let other routines run in the meantime.
  • Asynchronous code, through the mechanism above, facilitates concurrent execution. To put it differently, asynchronous code gives the look and feel of concurrency.

So asynchronous code is code that can hang while waiting for a result, in order to let other code run in the meantime. It doesn't "block" other code from running.

There are also third party libraries such as aiohttp and aiofiles for more specific use cases such as making HTTP requests and writing to files asynchronously. 

See you in 2038

This has been a nice walk down memory lane, and I hope it was useful to all of the cicadas reading. 17 years from now, they will reemerge, and I'm sure all sorts of technical wonders await them when they dig back into Python in 2038. It's up to us humans to make sure the Python language and community continues to flourish in the meantime.