Search code examples
pythonmultithreadingpython-multithreadingraw-input

Command line multithreading


I am writing a simple command-line program that shows the current time and let user set the alarm. However, the alarm did not ring as the raw_input was blocking it. I have even implement multithreading but it didn't work as well. Here's the full code:

import datetime, time, thread, os

program_running = True
now = datetime.datetime.now()
alarm_status = 0
alarm_hour = 0
alarm_minute = 0

def clock():
    now = datetime.datetime.now()
    print now.strftime('%H:%M')

def set_alarm():    
    global alarm_hour, alarm_minute, alarm_status

    alarm_time = raw_input('Set Alarm (XX:XX) : ')    
    alarm_hour = alarm_time[:alarm_time.find(':')]
    alarm_minute = alarm_time[alarm_time.find(':')+1:]
    alarm_status = 1 

def alert_thread():
    global alarm_hour, alarm_minute, alarm_status 
    while True:
        if(alarm_status):
                if (str(now.hour) == str(alarm_hour) and str(now.minute) == str(alarm_minute)):
                    print 'Ring.. Ring..'
                    alarm_status = 0

#program start here
thread.start_new_thread(alert_thread,())
while(program_running):
    now = datetime.datetime.now()


    print '1) Clock'
    print '2) Alarm'
    print '3) Quit'
    choice = input('Choose (1-6) : ')

    if(choice==1):
        clock()
    elif(choice==2):
        set_alarm()
    elif(choice==3):
        program_running = False

Solution

  • I find the implementation with globals and only a single thread for alarms a little strange. This way you can always only have set one alarm at a time and there will always be an alarm thread running even without any alarm being set. Also your now is never being updated to the alarm shouldn't run at all. Maybe consider doing it like this. This isjust a quick refactor, not saying this is perfect but it should help you get on:

    import datetime, time, threading, os
    
    
    def clock():
        now = datetime.datetime.now()
        print now.strftime('%H:%M')
    
    def set_alarm():    
        alarm_time = raw_input('Set Alarm (XX:XX) : ')    
        alarm_hour = alarm_time[:alarm_time.find(':')]
        alarm_minute = alarm_time[alarm_time.find(':')+1:]
        alarm_thread = threading.Thread(target=alert_thread, args=(alarm_time, alarm_hour, alarm_minute))
        alarm_thread.start()
    
    def alert_thread(alarm_time, alarm_hour, alarm_minute):
        print "Ringing at {}:{}".format(alarm_hour, alarm_minute)
        while True:
            now = datetime.datetime.now()
            if str(now.hour) == str(alarm_hour) and str(now.minute) == str(alarm_minute):
                print ("Ring.. Ring..")
                break
    
    
    #program start here
    while True:
        now = datetime.datetime.now()
        print '1) Clock'
        print '2) Alarm'
        print '3) Quit'
        choice = input('Choose (1-6) : ')
    
        if(choice==1):
            clock()
        elif(choice==2):
            set_alarm()
        elif(choice==3):
            break