Twitch client that notifies me when a followed streamer comes online I've been writing code for a little while but I'm a little slapdash. I'd like to get better so I've been having a glance at best practices, other peoples code and reading a whole lot. I'd appreciate it if you could read through my code and make some suggestions and explain why. You'll find some of my code below.

I want to start writing more readable code, follow best practices and just be awesome. Suggested reading would also be appreciated.

import requests
import json
import winsound
import time
import sys

USERNAME = "lirik"
FIRST_RUN = True
VERSION_NO = 1.0

def main():

    print "%s [+] Twitch Notifier %s started..." % (time.strftime("%H:%M:%S"), VERSION_NO)
    print "%s [+] Loading follows from %s" % (time.strftime("%H:%M:%S"), USERNAME)
    try:
        twitch_data = requests.get("https://api.twitch.tv/kraken/users/%s/follows/channels" % USERNAME)
    except:
        print "%s [+] Failed to contacted Twitch API" % time.strftime("%H:%M:%S")
        sys.exit(1)

    user_info = json.loads(twitch_data.text)  # load user data json into user_info
    users_online = list()  # initialise user_online list

    while True:
        for channel in user_info['follows']:  # Loop through channels in the users follow list
            stream_name = channel['channel']['name']  # Add channel name to var stream_name for simplicity
            try:
                stream_data = requests.get("https://api.twitch.tv/kraken/streams/%s" % stream_name)
            except:
                print stream_data.status_code
                print stream_data.text
                continue

            try:
                stream_info = json.loads(stream_data.text)
            except ValueError, e:
                print e
                continue

            if stream_info['stream']:
                if stream_name not in users_online:
                    print "%s [+] Online: %s [%s][%s]" % (time.strftime("%H:%M:%S"),
                                                          stream_name,
                                                          stream_info['stream']['game'],
                                                          stream_info['stream']['viewers'])
                    users_online.append(stream_name)
                    winsound.Beep(1000, 1000)
            else:
                if stream_name in users_online:
                    print "%s [+]Checking if %s is offline." % (time.strftime("%H:%M:%S"),
                                                                stream_name)
                    if chk_user_online(stream_name) is False:  #Double check if user is offline. Sometimes the twitch API fucks up.
                        print "%s [-] Offline: %s" % (time.strftime("%H:%M:%S"),
                                                      stream_name)
                        users_online.remove(stream_name)
                else:
                    pass
                    #print "[*] No change in users online."

        if len(users_online) &lt; 1 and first_run:
            first_run = False
            print "%s [*] There are currently no users online." % time.strftime("%H:%M:%S")

        time.sleep(180)

def chk_user_online(streamer):

    try:
        stream_data = requests.get("https://api.twitch.tv/kraken/streams/%s" % streamer)
        stream_info = json.loads(stream_data.text)
    except:
        print "Stream check failed."
        return Exception("Failed to access stream data")

    if stream_info['stream'] is None:
        return False
    else:
        return True


if __name__ == "__main__":
    main()
It's good that you use absolute imports instead of wildcard imports.


VERSION_NO = 1.0



While it is usually correct to use ALLCAPS for constants, the version number should be called __version__.  That way, the help() function will know which version the program is and will display it accordingly.

Using % for format strings is not officially deprecated, but it is recommended to use .format() instead since it is more flexible.

When you have a try: block, you presumable know what errors could possibly happen.  You should list those errors in your except: statement.  That way, if one comes up that you didn't expect, you will know about it.  You might want to have two except: blocks: one for the errors you know about, and one for all the rest.  The second might be except Exception as e: print e, "Something has gone wrong.  Please ..." or whatever.


except ValueError, e:



In Python2, you use parentheses around multiple errors that you want to catch, but the syntax used above means to call the error e.  In Python3, the parentheses are not needed, so what that line means is to catch all errors of type ValueError or of type e.  What you do in Python3 is to use except ValueError as e:  That is still possible in Python2, so to be in good practice, you should use it here.


if stream_info['stream'] is None:
    return False
else:
    return True



That's great that you used is None instead of == None.  Many people wouldn't do that.  The problem I have with this code is that if ... is checking if ... is True.  Since you are already creating a boolean, take advantage of it and do it in one line:

return stream_info['stream'] is not None