我正在使用python 2.7.10功能进行轮询数据,如果设备花费太长响应时间太长,或者如果该设备不可用,请捕获RuntimeError。我正在使用此超时功能:
class Timeout():
class Timeout(Exception):
pass
def __init__(self, sec):
self.sec = sec
def __enter__(self):
signal.signal(signal.SIGALRM, self.raise_timeout)
signal.alarm(self.sec)
def __exit__(self, *args):
signal.alarm(0)
def raise_timeout(self, *args):
raise Timeout.Timeout()
这是我进行数据投票(Modbus)并捕获异常的循环。此循环每60秒称为一次:
def getDeviceTags(name, tag_data):
global val_returns
for tag in tag_data[name]:
local_vals = []
local_vals.append(name+"."+tag)
try:
with Timeout(3):
value = modbus.read(str(name), str(tag))
local_vals.append(str(value.value()))
except RuntimeError:
print("RuntimeError on " + str(name))
local_vals.append(None)
except Timeout.Timeout:
print("Timeout on " + str(name))
local_vals.append(None)
val_returns.append(local_vals)
这将在没有问题的情况下一次工作几天,包括运行时间和超时打印到控制台上,所有数据已记录 - 很棒。但是,最近它被卡住了 - 这是我遇到的唯一错误:
Traceback (most recent call last):
File "working_one_min_back.py", line 161, in <module>
job()
File "working_one_min_back.py", line 79, in job
getDeviceTags(str(key), data)
File "working_one_min_back.py", line 57, in getDeviceTags
print("RuntimeError on " + str(name))
File "working_one_min_back.py", line 30, in raise_timeout
raise Timeout.Timeout()
__main__.Timeout
不能保证在访问 alarm(0)
之后不会传递" python信号"。实际(c)信号可能已经交付了,导致python处理程序稍后调用一些字体模式指令。
如果您从__exit__
调用signal.signal
,则任何此类待处理信号都是丢弃的,它会有效防止将其误以为 next 一个请求。无论如何,将其用于还原在创建Timeout
之前具有的处理程序(第一个signal.signal
调用返回)还是一个好主意。(在调用alarm(0)
以防止SIG_DFL
杀死该过程。)
在python&nbsp; 3中,这样的调用传递任何待处理信号而不是丢弃它们,这是一个改进,因为它仅仅因为处理程序更改了信号而阻止丢失信号。(不幸的是,这没有比Python&nbsp; 2行为更有记录。)您可以尝试通过在__exit__
中设置属性并忽略设置时引起的任何(python)信号来抑制这种后期信号。
当然,可以在__exit__
开始执行和丢弃信号之前(或标记为被忽略)后传递信号。因此,您必须处理操作完成和计时,也许是通过对单个变量进行几个分配,然后仅在一个地方进行 append
ed。