6
\$\begingroup\$

This program calculates up and downspeed of a given connection for as long as it is running.

#upspeed/downspeed indicator
#written by Chubak -> [email protected]

import requests
import time
import os

def get_seconds(datetime):
    time = datetime.split(' ')[3].split(':')

    time_hours = int(time[0])
    time_minutes = int(time[1])
    time_seconds = int(time[2])

    return time_hours*360 + time_minutes*60 + time_seconds




def downspeed():
    url = "http://speedtest.ftp.otenet.gr/files/test100k.db"

    current_seconds = get_seconds(time.asctime())

    file = requests.get(url)
    headers = file.headers

    file_size = int(headers['Content-Length'])/1000

    dl_seconds = get_seconds(time.asctime())

    time_difference = dl_seconds - current_seconds

    return round(file_size / time_difference)



def upspeed():
    current_seconds = get_seconds(time.asctime())

    dummy_file = os.path.join(os.getenv('APPDATA'), 'dummy.txt')
    post_url = 'http://httpbin.org/post'
    with open(dummy_file, 'wb') as dummy:
        for i in range (1500):
            dummy.write(str.encode('This is a dummy text. Its sole propose is being uploaded to a server. '))

        dummy.close()

    files = {'file' : open(dummy_file, 'rb')}

    request = requests.post(post_url, data=files)

    headers = request.headers

    file_size = int(headers['Content-Length'])/1000

    dl_seconds = get_seconds(time.asctime())

    time_difference = dl_seconds - current_seconds

    return round(file_size / time_difference)


if __name__ == '__main__':
    while True:
        up = None
        down = None

        if up == None and down == None:
            up = upspeed()
            down = downspeed()

            print('At {0} your Downspeed is: {1}, and your Upspeed is: {2}'.format(time.asctime(), down, up))

            time.sleep(5)

            up = None
            down = None

I'd appreciate it if your dropped any hints about turning this into a desktop widget.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ You forgot to mention that the APPDATA environment variable is required. \$\endgroup\$
    – zondo
    Commented Aug 22, 2016 at 2:04
  • 1
    \$\begingroup\$ Using bigger files (especially for upload), usually around 10mb will allow the speed to settle. For example when I start uploading something, it is at 50mbps but falls to 10mbps in a few secinds. \$\endgroup\$
    – ave
    Commented Aug 22, 2016 at 2:07

2 Answers 2

5
\$\begingroup\$

Your whole function get_seconds is not needed at all. You can use the function time.time(), which gives you the seconds since epoch (Jan 1, 1970 0:00:00). Subtracting two such times will yield the number of seconds passed in between. I would also do the time measurement exclusively around the actual download, otherwise you add the (small) overhead of reading the header for the file-size.

def downspeed():
    url = "http://speedtest.ftp.otenet.gr/files/test100k.db"

    start = time.time()
    file = requests.get(url)
    end = time.time()

    time_difference = end - start
    file_size = int(file.headers['Content-Length'])/1000    
    return round(file_size / time_difference)

You should also report the units of your speeds measured. As it is, they will be KB/s, with the K denoting 1000 (as you divide by that). You should be aware that there is also a different unit, sometimes written KiB/s, where Ki stands for 1024. You should probably use the same definition, which speedtest uses, when it says the file is 100kb big.

\$\endgroup\$
4
\$\begingroup\$

I don't know if this is the best way to measure internet speed or not. I won't comment whether this is the right approach. There are, however, some stylistic improvements that can be made.

You should run your code through pylint. Some issues could easily be addressed such as too many newlines between get_seconds and downspeed. pylint enforces two newlines.

This isn't English class, you don't have to double space your functions.

def downspeed():
    url = "http://speedtest.ftp.otenet.gr/files/test100k.db"

    current_seconds = get_seconds(time.asctime())

    file = requests.get(url)
    headers = file.headers

    file_size = int(headers['Content-Length'])/1000

    dl_seconds = get_seconds(time.asctime())

    time_difference = dl_seconds - current_seconds

    return round(file_size / time_difference)

Just do:

def downspeed():
    url = "http://speedtest.ftp.otenet.gr/files/test100k.db"
    current_seconds = get_seconds(time.asctime())
    file = requests.get(url)
    headers = file.headers
    file_size = int(headers['Content-Length'])/1000
    dl_seconds = get_seconds(time.asctime())
    time_difference = dl_seconds - current_seconds
    return round(file_size / time_difference)

Every once in a while you can add an additional newline for clarity, but don't over do it.

You don't need to define as many variables as you have. Consider:

def get_seconds(datetime):
    time = datetime.split(' ')[3].split(':')

    time_hours = int(time[0])
    time_minutes = int(time[1])
    time_seconds = int(time[2])

    return time_hours*360 + time_minutes*60 + time_seconds

Seeing something like int(time[0]) might be intimidating but adding comments to explain this stuff will

def get_seconds(datetime):
    """
    Takes a time of day and converts it to seconds.
    Args:
        datetime: Time of day as HH:MM:SS
    """
    time = datetime.split(' ')[3].split(':')
    # Hours + Minutes + Seconds
    return int(time[0])*360 + int(time[1])*60 + int(time[2])

Furthermore, you don't need the headers variables:

def downspeed():
    url = "http://speedtest.ftp.otenet.gr/files/test100k.db"
    current_seconds = get_seconds(time.asctime())
    file = requests.get(url)
    file_size = int(file.headers['Content-Length'])/1000
    dl_seconds = get_seconds(time.asctime())
    time_difference = dl_seconds - current_seconds
    return round(file_size / time_difference)

And:

def upspeed():
    current_seconds = get_seconds(time.asctime())
    dummy_file = os.path.join(os.getenv('APPDATA'), 'dummy.txt')
    post_url = 'http://httpbin.org/post'
    with open(dummy_file, 'wb') as dummy:
        for i in range(1500):
            dummy.write(str.encode('This is a dummy text. Its sole propose is being uploaded to a server. '))
        dummy.close()
    files = {'file' : open(dummy_file, 'rb')}
    request = requests.post(post_url, data=files)
    file_size = int(request.headers['Content-Length'])/1000
    dl_seconds = get_seconds(time.asctime())
    time_difference = dl_seconds - current_seconds
    return round(file_size / time_difference)

By convention when you don't use a variable in a loop, you use _. So:

for _ in range(1500):
    dummy.write(str.encode('This is a dummy text. Its sole propose is being uploaded to a server. '))

time_difference is often expressed as dt or ellapsed. Consider changing it.

Maybe make the url variables a default argument?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.