2017-01-02 121 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