GLHF
GLHF

Reputation: 4035

Time issue in Python

My program is working with input() from user. I want to print "hey,are you there?" when the user hasn't written anything in 5 seconds. For example, the user writes something, and stops typing. If the user waits more than 5 seconds, then I want to print "hey,are you there?". So far I tried this:

while True:
    start=time.time()
    x=input("enter something")
    end=time.time()
    dif=end-start
    if 5<dif:
        print("hey are you there?")

It didn't work as I expected, because it waits for the user. It's writing "hey are you there?" after the user wrote something. But I expect that when the user doesn't type anything, it also means x==False, I want to warn the user.

Update I tried this one:

import msvcrt
import time

time1 = 0

print('enter something: ')

while not msvcrt.kbhit():
    time.sleep(1)
    time1 +=1
    if time1 == 5:
        print("hey are you there?")

while msvcrt.kbhit():
    x = input()

It didn't work either. It printed "hey are you there?" after 5 seconds even x==True. So far no solution, hope I explained what I need.

Upvotes: 2

Views: 368

Answers (2)

Adam Smith
Adam Smith

Reputation: 54163

Having trouble getting msvcrt.kbhit to register and don't have time to debug at the moment, so I can't detect a key press to reset the timer. I'll edit when I can figure it out but working on this over my breaks at work since it seems like an interesting problem!

import threading
import queue
import msvcrt
import time

class Listener(threading.Thread):
    def __init__(self, msg, in_q):
        super().__init__()
        self.__in_q = in_q
        self.msg = msg

    def run(self):
        last_time = time.time()
        while True:
            try:
                self.__in_q.get_nowait()
            except queue.Empty:
                pass # no poison pill, continue
            else:
                return 0 # poison pill, so end
            cur_time = time.time()
            timedelta = cur_time - last_time
            if timedelta >= 5:
                last_time = cur_time
                print(self.msg)
            if msvcrt.kbhit():
                last_time = cur_time
                # THIS BLOCK IS NOT CURRENTLY WORKING
                # POSSIBLY msvcrt.kbhit WILL NOT CAPTURE THIS PROMPT?

if __name__ == "__main__":
    q = queue.Queue()
    listener = Listener("Are you still there?", q)
    listener.start()
    response = input("enter something: ")
    q.put("poison")

Using an implementation of input that Fred S hacked in, I was able to get this working as intended. It feels like kludge (and it is) but that's the best I can do on the command line in Windows.

import threading
import queue
import msvcrt
import time
import sys

class Listener(threading.Thread):
    def __init__(self, in_q, msg=""):
        super().__init__()
        self.__in_q = in_q
        self.msg = msg

    def run(self):
        last_time = time.time()
        while True:
            cur_time = time.time()
            try:
                tmp = self.__in_q.get_nowait()
            except queue.Empty:
                pass # no message, OK
            else:
                # message exists. Is it a poison pill?
                if tmp == "poison":
                    # poison pill, kill process
                    return
                else:
                    last_time = time.time()
                    # not poison pill, so refresh the timer
            timedelta = cur_time - last_time
            if timedelta >= 5:
                last_time = cur_time
                print(self.msg)

def new_input(prompt="", out_q=None):
    """Uses msvcrt.getch to simulate Py3's input
    allows you to pass a queue to receive each
    character."""

    result = ""
    print(prompt, end="")
    while True:
        sys.stdout.flush()
        ch = msvcrt.getch().decode()
        sys.stdout.write(ch)
        if out_q:
            out_q.put(ch)
        if "\r" in ch:
            return result
        else:
            result += ch

if __name__ == "__main__":
    q = queue.Queue()
    listener = Listener(q, "Are you still there?")
    listener.start()
    result = new_input("enter something: ", q)
    q.put("poison")
    print("You entered " + result)

Upvotes: 1

Fred S
Fred S

Reputation: 995

Seems like this works, but I'm using python 2.7:

    import threading, time

    class ValueGetter(object):
        def __init__(self, wait_time_sec = 5.0):
            self.stop_flag = True
            self.wait_time_sec = wait_time_sec

        def get_value(self):
            self.stop_flag = False
            p = threading.Thread(target=self.print_uthere)
            p.start()
            retval = raw_input('enter something:\n')
            self.stop_flag = True
            p.join()
            return retval

        def print_uthere(self):
            tprint = tnow = time.clock()
            while not self.stop_flag:
                if tnow > (tprint + self.wait_time_sec):
                    print 'Are you there???'
                    tprint = time.clock()
                time.sleep(0.01)
                tnow = time.clock()

    v = ValueGetter()
    print v.get_value()

Here is a modified version that will reset the 5 sec timer whenever they enter a key. Windows only though.

import threading, time, msvcrt, sys

class ValueGetter(object):
    def __init__(self, wait_time_sec = 5.0):
        self.stop_flag = True
        self.wait_time_sec = wait_time_sec
        self.tprint = self.tnow = time.clock()

    def get_value(self):
        self.stop_flag = False
        p = threading.Thread(target=self.print_uthere)
        p.start()
        print 'enter something:'
        retval = ''
        ch = ''
        while not ch == '\r':
            retval += ch
            ch = msvcrt.getch()
            sys.stdout.write(ch)
            self.tprint = time.clock()
        print
        self.stop_flag = True
        p.join()
        return retval

    def print_uthere(self):
        self.tprint = self.tnow = time.clock()
        while not self.stop_flag:
            if self.tnow > (self.tprint + self.wait_time_sec):
                print 'Are you there???'
                self.tprint = time.clock()
            time.sleep(0.01)
            self.tnow = time.clock()

v = ValueGetter()
print v.get_value()

Upvotes: 2

Related Questions