我正在阅读python threading
和timer
子类上的文档,如果我想以不同的速率运行两个(或多个)定时类方法,我不太了解它的工作方式相同的线程。
例如,我有一个I / O串行设备,我想定期读取(如果有数据),从外部模块写入任何输入消息,并定期写入预定义的设备特定心跳消息。所有这些都包装在一个自定义类中。 I / O消息存储在两个单独的类队列对象中。
我需要为每个函数创建三个threading.Timer
对象,还是可以以某种方式使用一个可以切换的线程?
import serial, threading, Queue
# the exact syntax below may be incorrect
class MySerialDevice:
def __init__():
# Some other modules will be appending to this (through a class method)
self.write_queue = Queue()
self.read_queue = Queue()
self.port = serial.Serial()
# check for incoming data every 20ms
self.thread1 = threading.Timer(0.02, self.read)
# check for outgoing data every 20ms
self.thread2 = threading.Timer(0.02, self.write)
# Send the heaertbeat every 1 second
self.thread3 = threading.Timer(1, self.heartbeat)
# what do I do here???
# can I make all three tasks on a single thread, that just continuously loops
# and "if incoming data, read, if outgoing data, write, heartbeat???
def read(self):
# checks for actual data, appending to queue are ommited
self.port.read()
def write(self):
# checks for data in queue ommitted
self.port.write(self.write_queue[0])
def heartbeat(self):
self.port.write("Device Heartbeat message)"
答案 0 :(得分:0)
Timer
很简单;没有比您看到的更多的东西了。它只运行一个计时器,一次,占用整个线程。
实际上,它作为示例代码确实比其他任何东西都多。其文档中的第二句话是“ Timer
是Thread
的子类,因此也可以作为创建自定义线程的示例。”并且threading
文档链接到the source,您可以看到它很简单。
从该示例代码中构建更复杂的东西并不难。
ActiveState食谱集合中曾经有一些很好的例子。我不知道如何搜索他们的新仓库,但是您可以从a tag lookup开始。
或者,在PyPI上可以使用一堆更强大的调度程序。
或者您可以使用tick
方法来重写代码。如果您每隔20毫秒进行一次滴答,则read
和write
会在每个滴答滴答声中运行,而heartbeat
每隔50滴答滴答地跑一次,对吧?
def __init__(self):
self.tickcount = 0
self.timer = threading.Timer(0.02, self.tick)
def tick(self):
self.read()
self.write()
self.tickcount += 20
if not self.tickcount % 1000:
self.heartbeat()
self.timer = threading.Timer(0.02, self.tick)
但是,在这一点上,编写一个每20ms循环一次的函数而不是使用计时器几乎一样简单。如果例如您需要担心不累积滞后,则扩展起来会容易得多。例如:
def ticker(self):
last = datetime.datetime.now()
while True:
wake = last + datetime.timedelta(milliseconds=20)
now = datetime.datetime.now()
while wake > now:
time.sleep((wake - now).total_seconds())
self.tick()
last = wake
现在您可以在线程中运行self.ticker
。
或者您可以只使用多个Timer
对象。您在谈论几个对象,每个对象三个计时器,对吗?看来这不是最优雅的解决方案,但这并不会给调度程序带来负担。