睡不着打断程序

时间:2017-01-02 03:06:36

标签: python multithreading python-3.x

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

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

有2个问题。

  1. 我希望时间在一秒钟之后仍能保持稳定,但不要在输入之前等待第二秒。与this相似。我想我需要使用线程。

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

  3. 感谢您的帮助。

2 个答案:

答案 0 :(得分: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秒钟,然后开始打印“Wuf-wuf!”每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()

带线程的简易版本(但有点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会在输入()输出的提示信息之后插入打印文本。

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

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

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

答案 1 :(得分:0)

您需要使用线程来执行此操作。您所要做的就是创建this example的子类覆盖threading.Thread方法,并在线程上添加一些外部控制方法。

这是一个简单的例子,您可以根据自己的喜好尝试和调整。

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

如果你想认真对待它,请不要忘记run()