我能以某种方式避免在此脚本中使用 time.sleep() 吗?
Can I somehow avoid using time.sleep() in this script?
我有以下 python 脚本:
#! /usr/bin/python
import os
from gps import *
from time import *
import time
import threading
import sys
gpsd = None #seting the global variable
class GpsPoller(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
global gpsd #bring it in scope
gpsd = gps(mode=WATCH_ENABLE) #starting the stream of info
self.current_value = None
self.running = True #setting the thread running to true
def run(self):
global gpsd
while gpsp.running:
gpsd.next() #this will continue to loop and grab EACH set of gpsd info to clear the buffer
if __name__ == '__main__':
gpsp = GpsPoller() # create the thread
try:
gpsp.start() # start it up
while True:
print gpsd.fix.speed
time.sleep(1) ## <<<< THIS LINE HERE
except (KeyboardInterrupt, SystemExit): #when you press ctrl+c
print "\nKilling Thread..."
gpsp.running = False
gpsp.join() # wait for the thread to finish what it's doing
print "Done.\nExiting."
不幸的是,我对 python 不是很好。该脚本应该以某种方式是多线程的(但这在这个问题的范围内可能无关紧要)。
令我困惑的是 gpsd.next()
行。如果我做对了,它应该告诉脚本新的 gps 数据已经获取并准备好读取。
但是,我使用无限 while True
循环读取数据,其中暂停 1 秒 time.sleep(1)
。
但是,它的作用是有时会重复两次相同的数据(传感器在最后一秒没有更新数据)。我想它也会以某种方式跳过一些传感器数据。
我能否以某种方式更改脚本以不是每秒打印当前速度,而是每次传感器报告新数据时打印当前速度?根据数据sheet应该是每秒一次(一个1赫兹的传感器),但显然不是精确的1秒,而是以毫秒为单位变化的。
我在这里看到两个选项:
- GpsPoller 将检查数据是否更改并发出标志
- GpsPoller 将检查已更改的 id 数据并将新数据放入队列中。
选项#1:
global is_speed_changed = False
def run(self):
global gpsd, is_speed_changed
while gpsp.running:
prev_speed = gpsd.fix.speed
gpsd.next()
if prev_speed != gpsd.fix.speed
is_speed_changed = True # raising flag
while True:
if is_speed_changed:
print gpsd.fix.speed
is_speed_changed = False
选项 #2(我更喜欢这个,因为它可以保护我们免受加薪条件的影响):
gpsd_queue = Queue.Queue()
def run(self):
global gpsd
while gpsp.running:
prev_speed = gpsd.fix.speed
gpsd.next()
curr_speed = gpsd.fix.speed
if prev_speed != curr_speed:
gpsd_queue.put(curr_speed) # putting new speed to queue
while True:
# get will block if queue is empty
print gpsd_queue.get()
作为通用设计规则,每个输入通道应有一个线程,或者更通用的是,每个 "loop over a blocking call"。阻塞意味着执行在该调用处停止,直到数据到达。例如。 gpsd.next()
就是这样的称呼。
要同步多个输入通道,请使用 Queue
和一个额外的线程。每个输入线程都应将其 "events" 放在(相同的)队列中。额外的线程遍历 queue.get()
并做出适当的反应。
从这一点来看,您的脚本不需要多线程,因为只有一个输入通道,即 gpsd.next()
循环。
示例代码:
from gps import *
class GpsPoller(object):
def __init__(self, action):
self.gpsd = gps(mode=WATCH_ENABLE) #starting the stream of info
self.action=action
def run(self):
while True:
self.gpsd.next()
self.action(self.gpsd)
def myaction(gpsd):
print gpsd.fix.speed
if __name__ == '__main__':
gpsp = GpsPoller(myaction)
gpsp.run() # runs until killed by Ctrl-C
请注意 action
回调的使用如何将管道与数据评估分开。
要将轮询器嵌入到执行其他操作的脚本中(即也处理其他线程),请使用队列方法。示例代码,基于 GpsPoller
class:
from threading import Thread
from Queue import Queue
class GpsThread(object):
def __init__(self, valuefunc, queue):
self.valuefunc = valuefunc
self.queue = queue
self.poller = GpsPoller(self.on_value)
def start(self):
self.t = Thread(target=self.poller.run)
self.t.daemon = True # kill thread when main thread exits
self.t.start()
def on_value(self, gpsd):
# note that we extract the value right here.
# Otherwise it could change while the event is in the queue.
self.queue.put(('gps', self.valuefunc(gpsd)))
def main():
q = Queue()
gt = GpsThread(
valuefunc=lambda gpsd: gpsd.fix.speed,
queue = q
)
print 'press Ctrl-C to stop.'
gt.start()
while True:
# blocks while q is empty.
source, data = q.get()
if source == 'gps':
print data
我们给 GpsPoller 的 "action" 表示 "calculate a value by valuefunc and put it in the queue"。 mainloop 一直坐在那里直到弹出一个值,然后打印它并继续。
将其他Thread的事件放入队列中,并添加适当的处理代码也很简单。
我有以下 python 脚本:
#! /usr/bin/python
import os
from gps import *
from time import *
import time
import threading
import sys
gpsd = None #seting the global variable
class GpsPoller(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
global gpsd #bring it in scope
gpsd = gps(mode=WATCH_ENABLE) #starting the stream of info
self.current_value = None
self.running = True #setting the thread running to true
def run(self):
global gpsd
while gpsp.running:
gpsd.next() #this will continue to loop and grab EACH set of gpsd info to clear the buffer
if __name__ == '__main__':
gpsp = GpsPoller() # create the thread
try:
gpsp.start() # start it up
while True:
print gpsd.fix.speed
time.sleep(1) ## <<<< THIS LINE HERE
except (KeyboardInterrupt, SystemExit): #when you press ctrl+c
print "\nKilling Thread..."
gpsp.running = False
gpsp.join() # wait for the thread to finish what it's doing
print "Done.\nExiting."
不幸的是,我对 python 不是很好。该脚本应该以某种方式是多线程的(但这在这个问题的范围内可能无关紧要)。
令我困惑的是 gpsd.next()
行。如果我做对了,它应该告诉脚本新的 gps 数据已经获取并准备好读取。
但是,我使用无限 while True
循环读取数据,其中暂停 1 秒 time.sleep(1)
。
但是,它的作用是有时会重复两次相同的数据(传感器在最后一秒没有更新数据)。我想它也会以某种方式跳过一些传感器数据。
我能否以某种方式更改脚本以不是每秒打印当前速度,而是每次传感器报告新数据时打印当前速度?根据数据sheet应该是每秒一次(一个1赫兹的传感器),但显然不是精确的1秒,而是以毫秒为单位变化的。
我在这里看到两个选项:
- GpsPoller 将检查数据是否更改并发出标志
- GpsPoller 将检查已更改的 id 数据并将新数据放入队列中。
选项#1:
global is_speed_changed = False
def run(self):
global gpsd, is_speed_changed
while gpsp.running:
prev_speed = gpsd.fix.speed
gpsd.next()
if prev_speed != gpsd.fix.speed
is_speed_changed = True # raising flag
while True:
if is_speed_changed:
print gpsd.fix.speed
is_speed_changed = False
选项 #2(我更喜欢这个,因为它可以保护我们免受加薪条件的影响):
gpsd_queue = Queue.Queue()
def run(self):
global gpsd
while gpsp.running:
prev_speed = gpsd.fix.speed
gpsd.next()
curr_speed = gpsd.fix.speed
if prev_speed != curr_speed:
gpsd_queue.put(curr_speed) # putting new speed to queue
while True:
# get will block if queue is empty
print gpsd_queue.get()
作为通用设计规则,每个输入通道应有一个线程,或者更通用的是,每个 "loop over a blocking call"。阻塞意味着执行在该调用处停止,直到数据到达。例如。 gpsd.next()
就是这样的称呼。
要同步多个输入通道,请使用 Queue
和一个额外的线程。每个输入线程都应将其 "events" 放在(相同的)队列中。额外的线程遍历 queue.get()
并做出适当的反应。
从这一点来看,您的脚本不需要多线程,因为只有一个输入通道,即 gpsd.next()
循环。
示例代码:
from gps import *
class GpsPoller(object):
def __init__(self, action):
self.gpsd = gps(mode=WATCH_ENABLE) #starting the stream of info
self.action=action
def run(self):
while True:
self.gpsd.next()
self.action(self.gpsd)
def myaction(gpsd):
print gpsd.fix.speed
if __name__ == '__main__':
gpsp = GpsPoller(myaction)
gpsp.run() # runs until killed by Ctrl-C
请注意 action
回调的使用如何将管道与数据评估分开。
要将轮询器嵌入到执行其他操作的脚本中(即也处理其他线程),请使用队列方法。示例代码,基于 GpsPoller
class:
from threading import Thread
from Queue import Queue
class GpsThread(object):
def __init__(self, valuefunc, queue):
self.valuefunc = valuefunc
self.queue = queue
self.poller = GpsPoller(self.on_value)
def start(self):
self.t = Thread(target=self.poller.run)
self.t.daemon = True # kill thread when main thread exits
self.t.start()
def on_value(self, gpsd):
# note that we extract the value right here.
# Otherwise it could change while the event is in the queue.
self.queue.put(('gps', self.valuefunc(gpsd)))
def main():
q = Queue()
gt = GpsThread(
valuefunc=lambda gpsd: gpsd.fix.speed,
queue = q
)
print 'press Ctrl-C to stop.'
gt.start()
while True:
# blocks while q is empty.
source, data = q.get()
if source == 'gps':
print data
我们给 GpsPoller 的 "action" 表示 "calculate a value by valuefunc and put it in the queue"。 mainloop 一直坐在那里直到弹出一个值,然后打印它并继续。
将其他Thread的事件放入队列中,并添加适当的处理代码也很简单。