Hi,

I'm a c++ guy trying to learn python. I'm trying to code something which models how a jukebox would work. The code I've attached simply adds numbers to a list on keypresses (enqueuing) and then other threads remove them (the player).

My problem goes like this: When I press a key the system works as it should. If I press a key twice quite quickly its still ok. However, if I push a key 3 times or more in quick succession then the third and later events which I think should get triggered don't.

My understanding of threads in python is very limited. In fact this is pretty much my first shot at python. There's clearly some important point I'm missing, ...what is it please?

import threading, random, time, Tkinter as tk, sys

# globals 

# (locks, events and lists)
shortener_done = threading.Event()
list_lock = threading.Lock()
removing_lock = threading.Lock()
the_list = []

# system values

#
# keypress listener, can be made into a remote controll listener
#
def keypressListener(event):
    if event.keysym == 'Escape':#
        keyWin.destroy()
        print 'exiting\n'
        # harsh shutdown...
        sys.exit(0)
    else:
        local_longener = longener()
        local_longener.start()

#
# add an item to the list
#
class longener( threading.Thread ):
    def __init__( self ):
        threading.Thread.__init__(self)

    def run( self ):
        # generate a number
        ran_num = random.randint(1,100)
        
        # put it on the list
        list_lock.acquire()
        the_list.append(ran_num)
        print 'Just appended: ' , ran_num , ' to the list... ', len(the_list)

        # check to see if we just 
        if(len(the_list) == 1):
            print 'starting shortener'
            local_shortener = shortener()
            local_shortener.start()
        list_lock.release()
            
#
# remove and item from the list
#
class shortener( threading.Thread ):
    def __init__( self ):
        threading.Thread.__init__(self)

    def run( self ):
        # we only want one shortener running at a time..
        removing_lock.acquire()
        # get the value from the list (and shorten it too)
        list_lock.acquire()
        if(len(the_list) > 0):
            value = the_list.pop(0)
            print 'removing value: ' , value , ' from the list... ...' , len(the_list)
            list_lock.release()
            # do some time consuming stuff
            time.sleep(2)
            print 'removed value: ' , value , ' from the list...' , len(the_list)
        else:
            list_lock.release()
        # signal that we're done
        removing_lock.release()
        print 'sending shortener done'
        shortener_done.set()
        shortener_done.clear()


#
# waits on event "shortener_done"
# calls a new shortener whenever the system
# goes idle and the list is non-empty
#
class sd_controller( threading.Thread ):

    def __init__( self ):
        threading.Thread.__init__(self)
    
    def run( self ):
        while(1):
            # whenever a shortener is done, start a new one (perhaps)
            shortener_done.wait()
            list_lock.acquire()
            if(len(the_list) > 0):
                print 'making new shortener'
                local_shortener = shortener()
                local_shortener.start()
            else:
                print 'zero list'
            list_lock.release()
    
# start the non-empty list listener
my_sd_cont = sd_controller()
my_sd_cont.start

# start a window and grab key presses
keyWin = tk.Tk()
print "Press a key (Escape key to exit):"
keyWin.bind_all('<Key>', keypressListener)
keyWin.mainloop()

if you don't mind about the learn curve then learn wxpython. It is very elegant in handling events. I have no way to understand TK for now. So sorry, someone will jump in the wagon ;)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.