【问题标题】:Time issue in PythonPython中的时间问题
【发布时间】:2015-02-10 11:51:12
【问题描述】:

我的程序正在使用来自用户的 input()。当用户在 5 秒内没有写任何东西时,我想打印 "hey,are you there?"。例如,用户写了一些东西,然后停止打字。如果用户等待超过 5 秒,那么我想打印"hey,are you there?"。到目前为止,我尝试过这个:

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

它没有像我预期的那样工作,因为它在等待用户。在用户写了一些东西之后,它正在写"hey are you there?"。但我希望当用户不输入任何内容时,也意味着x==False,我想警告用户。

更新我试过这个:

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()

它也没有工作。它在 5 秒后打印了 "hey are you there?",甚至是 x==True。到目前为止还没有解决方案,希望我解释了我需要什么。

【问题讨论】:

  • 这将比您想象的要困难得多。请参阅此relevant xkcd,其中一些编程问题很难衡量它们的难度!这与“几乎不可能”相去甚远,但如果不探索线程和从标准输入持续读取,就无法做到这一点。
  • 我也尝试过线程,仍然找不到任何解决方案。
  • 我将通过构建一个线程来解决此问题,该线程侦听msvcrt.kbhit() 并在无限循环中跟踪最后一次按下按钮,直到它从消息中接收到毒丸。如果当前时间比最后一个 kbhit 长 5 秒,它应该在标准输出中放入一条消息并将其最后一次设置为现在。当用户完成输入后,主线程应该发送毒丸。
  • stackoverflow Python 大师在哪里啊 :-/ 我真的很想解决这个问题
  • 我可以整理一些东西,但我现在正在工作,没有时间空闲。我会添加书签,稍后再回来,以防没有人回答

标签: python python-3.x time msvcrt


【解决方案1】:

似乎这样可行,但我使用的是 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()

这是一个修改版本,只要他们输入一个键,就会重置 5 秒计时器。但仅限 Windows。

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()

【讨论】:

  • 此方法的缺点是如果用户在 5 秒到期时正在输入内容,您仍将打印消息。
  • 和别人没什么区别,还是先等待用户输入。
  • 如果用户在 5 秒内没有完成输入,它将打印消息。之后每 5 秒一次。
  • 没有,等待输入
  • 线程在等待用户输入时正在运行,它将每 5 秒打印一次“你在吗”,直到它停止。你运行过这段代码吗?
【解决方案2】:

无法让msvcrt.kbhit 注册并且目前没有时间调试,所以我无法检测到按键来重置计时器。我会在我能弄明白的时候进行编辑,但我会在工作休息时间处理这个问题,因为这似乎是一个有趣的问题!

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")

使用 Fred S 入侵的 input 的实现,我能够按预期工作。感觉就像杂乱无章(确实如此),但这是我在 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)

【讨论】:

  • 警告信息仍在等待用户输入,5 秒后未弹出。而且 response=input() 必须在一段时间内为真:循环。但这是一个很好的步骤,已被应用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-04
  • 2023-04-04
  • 2019-07-17
  • 2015-08-23
  • 1970-01-01
相关资源
最近更新 更多