首先尝试在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 %
....你可以看到线程仍在轮询。
答案 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