2017-01-02 65 views
2

我正在创建一个程序,在一段时间后倒计时,并要求输入秒数来添加到倒计时。 (不是真的,只是一个例子)。 有点这样:睡眠不中断程序

mytime = 10 
while True: 
    print(time) 
    mytime -= 1 
    time.sleep(1) 
    mytime += int(input('add > ')) 

有2个问题。

  1. 我希望时间在一秒钟后仍然打勾,但不希望在输入之前等待第二秒。类似于this。我想我需要使用线程。

  2. 我不想等待输入!我只想让它在不等待输入的情况下打勾,当我想要的时候我可以输入内容。

感谢您的帮助。

+2

你绝对需要穿线。 –

+0

您称为可变时间和使用时间模块。 2个相同的名字。 – Dalen

+0

哎呦!!!!!!!!!!! – lol

回答

2

没有比为你准备的0计时器线程使自己的线程更简单的方法:“世界城市论坛,世界城市论坛”

import threading 

timer = None 

def wuf(): 
    global timer 
    print "Wuf-wuf!" 
    timer = threading.Timer(5, wuf) 
    timer.start() 

timer = threading.Timer(5, wuf) 
timer.start() 
input() # Don't exit the program 

该代码将等待5秒钟,然后开始打印每5秒钟一次。

如果你想从主线程阻止它这样做:

timer.cancel() 

但如果您使用的是事件驱动的GUI系统,如wxPython的或PyQt的编写GUI应用程序,那么你应该使用他们的事件管理计时器。特别是如果你正在从定时器回调改变一些GUI状态。

编辑: 哦,没事,这里是你的完整的答案:

import threading 

seconds = 1 # Initial time must be the time+1 (now 0+1) 
timer = None 
def tick(): 
    global seconds, timer 
    seconds -= 1 
    if seconds==0: 
     print("%i seconds left" % seconds) 
     print("Timer expired!") 
     return 
    # printing here will mess up your stdout in conjunction with input() 
    print("%i second(s) left" % seconds) 
    timer = threading.Timer(1, tick) 
    timer.start() 

seconds += int(input("Initial countdown interval: ")) 
tick() 
while 1: 
    seconds += int(input("Add: ")) 
    if not timer.is_alive(): 
     print("Restarting the timer!") 
     seconds += 1 
     tick() 

或Easy版本螺纹(但有点clumsyer然后使用threading.Thread):

from thread import start_new_thread as thread 
from time import sleep 

seconds = 1 # Initial time+1 
alive = 0 
def _tick(): 
    global seconds, alive 
    try: 
     alive = 1 
     while 1: 
      seconds -= 1 
      if seconds==0: 
       print("%i seconds left" % seconds) 
       print("Timer expired!") 
       alive = 0 
       return 
      # printing here will mess up your stdout in conjunction with input() 
      print("%i second(s) left" % seconds) 
      sleep(1) 
    except: alive = 0 

def tick(): 
    thread(_tick,()) 

# Then same as above: 
seconds += int(input("Initial countdown interval: ")) 
tick() 
while 1: 
    seconds += int(input("Add: ")) 
    if not alive: 
     print("Restarting the timer!") 
     seconds += 1 
     tick() 

你必须认识到,在线程内使用stdout将在input()输出的提示消息之后插入打印的文本。

这会令人困惑。如果你想避免这一点,那么你将不得不编写另一个线程来从队列中获取消息并输出它们。

如果最后一条消息是提示消息,则必须将其从屏幕上移除,写入新消息,然后返回提示消息,并相应地定位光标。

你可以通过在线程的子类中实现类文件接口来实现。线程,然后用它替换sys.stdout。也许重写input()以指示何时提示消息不存在,并读取stdin。

+0

谢谢,但这并没有完全回答我的问题。 – lol

+0

程序如何被每次调用?我看不到一个真正的循环。 – lol

+0

程序没有被调用,函数wuf()是。每次。 Timer()启动一个线程,它启动并等待,间隔到期后它调用给定的函数并停止。函数wuf()设置一个新的Timer(),在间隔到期后再次调用它。这正是你想要的,你只需要正确使用它。 – Dalen

0

您将需要使用线程来完成此操作。你所要做的就是创建threading.Thread的子类,覆盖run()方法,并在该线程上添加一些外部控制方法。

下面是一个简单的例子,您可以尝试根据自己的口味进行调整。

import threading 
import time 

class SleepingThread(threading.Thread): 

    def __init__(self, sleep_for): 
    super(SleepingThread, self).__init__() 
    self.sleep_for = sleep_for 

    def run(self): 
    while self.sleep_for != 0: 
     time.sleep(1) 
     self.sleep_for -= 1 
    print("Done sleeping") 

    def add_seconds(self, seconds): 
    self.sleep_for += seconds 

    def get_sleep_for(self): 
    return self.sleep_for 

sleeping_thread = SleepingThread(10) 
sleeping_thread.start() 
while True: 
    print(sleeping_thread.get_sleep_for()) 
    sleeping_thread.add_seconds(int(input('add > '))) 

,如果你想要去认真对待它,不要忘了join()

+0

这不完全是我想要的。它仍然等待输入,并且我希望它在每次输入减少时都打印新的时间,而不是在输入之后。 – lol