Python线程不停止

时间:2016-01-09 21:04:51

标签: python multithreading

首先尝试在python中进行线程化,在Stack上发布帖子之后线程正在工作但是我无法使用ctrl-c停止线程,尽管我的类中有一个使用键盘中断调用的终止方法。

基本上我在后台轮询温度传感器并使用线程来执行此操作,而代码的主体正在观看GPIO输入,一切正常,它只是线程让我感到困惑/

(那里有意图重新打印消息,所以我可以理解它出错的地方等)

class GetClimate(threading.Thread):
  def __init__(self):
    self._running = True
    print "Data Collection STARTED"
  def terminate(self):
    self._running = False
    print "Data Collection ENDED"
  def run(self):
    while self._running is True:
      ts = time.time()
      global GARAGE_HUM, GARAGE_TEMP
      timestamp = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
      GARAGE_HUM, GARAGE_TEMP = Adafruit_DHT.read_retry(Adafruit_DHT.DHT22, 4)
      if GARAGE_HUM is not None and GARAGE_TEMP is not None:
        print timestamp + " - Temperature: %.1f c" % GARAGE_TEMP
        print timestamp + " - Humidity:    %.1f %%" % GARAGE_HUM
        time.sleep(5) # seconds between sample

#---------Start Getting Climate data------------

def StartClimate():
    c = GetClimate()
    t = threading.Thread(target=c.run)
    t.start()
    print "Started Climate"
#--------Stop Climate Data----------------------
def StopClimate():
    print "Called Climate stop .."
    c = GetClimate()
    c.terminate()
    print "Stopped Climate"

当使用ctrl-c时,它会调用StopClimate()函数,因为它输出:

Data Collection STARTED
Started Climate
..Ready
2016-01-09 20:48:45 - Temperature: 24.8 c
2016-01-09 20:48:45 - Humidity:    51.9 %
Shutdown requested...exiting
Called Climate stop ..
Data Collection STARTED
Data Collection ENDED
Stopped Climate
^C2016-01-09 20:48:51 - Temperature: 24.8 c
2016-01-09 20:48:51 - Humidity:    51.9 %
2016-01-09 20:48:57 - Temperature: 24.7 c
2016-01-09 20:48:57 - Humidity:    51.8 %

....你可以看到线程仍在轮询。

3 个答案:

答案 0 :(得分:0)

在StopClimate中,您实例化一个新线程 - 因此STARTED消息 - 并立即终止它,而不调用其run方法。但是,您在StartClimate中实例化的原始线程不会受到任何影响。这是您存储在t中的线程,您需要终止它。

答案 1 :(得分:0)

您的来电' c = GetClimate()'在StartClimate和StopClimate中,每个都创建一个GetClimate实例。因此,您在StopClimate中终止的GetClimate不是您在StartClimate中启动的GetClimate。

此外,构建代码的方式,没有必要让GetClimate成为threading的子类。因为你在一个单独的线程中调用GetClimate run()方法(t =线程) .Thread(target = c.run()line。)

我建议您使用StartClimate()返回c,将结果存储在某处,然后将c作为参数传递给StopClimate()。这仍然不是构建所有这些的最佳方式,但它是对代码的最小改动。

答案 2 :(得分:0)

  • 每次调用函数时都会创建新实例。 这不会阻止现有的线程。

  • 当您将run方法用于Thread的新实例时,您不会使用自己的类,而是使用threading.Event方法。

  • 您应该使用bool代替time.sleep变量和PeriodicThread

这是一个基本interval,每隔from threading import Thread, Event from time import sleep class PeriodicThread(Thread): def __init__(self, interval): self.stop_event = Event() self.interval = interval super(PeriodicThread, self).__init__() def run(self): while not self.stop_event.is_set(): self.main() # wait self.interval seconds or until the stop_event is set self.stop_event.wait(self.interval) def terminate(self): self.stop_event.set() def main(self): print('Hello World') 秒调用一次主方法:

if __name__ == '__main__':
    # the workers main function is called and then 5 seconds sleep
    worker = PeriodicThread(interval=5)
    worker.start()

    try:
       # this is to keep the main thread alive
       while True:
           sleep(1)
    except (KeyboardInterrupt, SystemExit):
        worker.terminate()

你会像这样使用它:

time.time

一些小评论

  • 如果您使用的是日期时间,则无需拨打datetime.datetime.now(),您可以使用datetime.datetime.utcnow()表示当地时间,或from datetime import datetime class GetClimate(PeriodicThread): def main(self): timestamp = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S') temperature, humidity = Adafruit_DHT.read_retry(Adafruit_DHT.DHT22, 4) if temperature is not None and humidity is not None: print(timestamp + ' - Temperature: {:.1f} C'.format(temperature)) print(timestamp + ' - Humidity: {:.1f} %'.format(humidity)) self.temperature = temperature self.humidity = humidity 表示使用时间。

  • 我不会使用全局变量,使它们成为您更新的类的成员。

因此,使用此代码,您的代码将成为:

bowser.version