Most of you are probably familiar with https://speedtest.net, a website that measures the speed of your internet connection and reports your download, upload and ping speeds.
Did you know that Speedtest made a Python module for it? It is called speedtest-cli
, and it's a little old but still works admirably well. I'm going to show you how to use it to measure your network speed from within Python?
What if I told you that this speedtest-cli
module powers the speedtest-cli command line program as well? The one referenced in their announcement. It may even be powering the main speedtest.net site as well.
So by understanding how this program works, you gain the enormous potential of making something scalable using speedtest.net services.
Why measure within Python?
There are some advantages to running a speedtest using an API vs. a shell command.
- You can easily parse the output and errors
- No informational output is printed to standard error
- It is easier to pass arguments to an API call than a shell script called from a Python program.
So let's see how this speedtest-cli thing works, shall we?
The API calls
Installation is dead simple; you just run pip install speedtest-cli
. This doesn't need it's own section.
Note: installing the speedtest-cli module also installs the speedtest-cli command line program.
Getting a list of servers
import speedtest
s = speedtest.Speedtest()
servers = s.get_servers()
This returns 49 speedtest.net servers for now, this number will go up or down depending on if speedtest.net creates and deletes servers, which are hosted by ISPs at their datacenters. The result is a dictionary of servers categorized by distance. In other words, the distances are the dictionary keys, and they are floating-point numbers. The best way to iterate through this structure therefore is using [*s.get_servers().values()]
.
s.get_best_server()
Returns the nearest server, the one with the smallest distance.
s.download(threads=None)
s.upload(threads=None, pre_allocate=True)
These two functions perform the download and upload tests respectively and return similar structures. The threads
keyword argument takes a number that determines the number of threads to use for the test. By default it is None
, which means the speedtest.net server decides how many threads to use.
If pre_allocate=True
(upload()
only), then the entire upload data is stored in memory before running the test. This improves the upload performance and thus result somewhat, but it might cause you to run out of memory on small-memory systems, so you can set it to False
to disable that, and store the upload data piece by piece.
s.results.share()
Makes an HTTP POST request to speedtest.net with your results and returns a link to an image of your results, such as this:
Thanks for reading
If you see any errors in this post, please let me know so I can correct them.
Top comments (4)
836mbps?😳
This is a test server I rented from Leaseweb for the purposes of this article.
Hey, Nice Article.
one other thing I was expecting from this was that how speedtest works internally. How the speed of the internet is measured. It would be great if you could add that part also here
From my observations in the speedtest-cli code, it appears that each major data center is hosting the server-side part where speedtest-cli uploads to and downloads from as part as those tests. It also collects the upload, download speeds, latency of the connection and also naming information about the data center itself.
But here is the most important part: The upload and download tests are sending chunks of data in an interval. Sequences of repeated
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
strings. The size of each chunk is about 10KB. It's probably to give speedtest a more uniform measurement of how fast that chunk size gets through, as opposed to sending strings of different sizes.Here is where the chunk data is assembled. Then it's put in a GET or PUT request depending on the test. The function name is a misnomer: It doesn't actually read anything from a file even though it's called for both upload and download tests.