我正在编写一个脚本,用于从单线传感器获取温度并将温度输入到 Redis 中。该脚本从名为 alias1.py 的文件中获取单线设备列表,该文件包含成对的友好名称和单线总线传感器地址,并依次获取每个设备的温度。但是,如果传感器不可用,我想捕获异常并跳过它。目前这只是将它设置为 6 度,但我稍后可能会更改操作。不幸的是,我在这方面遇到了困难,在其他情况下看不到直接的平行关系。
#!/usr/bin/python3
import logging
from onewire import Onewire
import redis
from alias1 import sensors
logging.basicConfig(level=logging.DEBUG)
room_float = {}
room_integer = {}
rooms ={}
ow = Onewire("%s:%d" % ("localhost", 4304))
for key in sensors:
roomID = sensors[key]
s = ow.sensor(roomID)
try:
temperature = s.read("temperature")
logging.info("found device %s (type = %s)" % (s.path,s.sensor_type))
except (RuntimeError, TypeError, NameError, AttributeError):
temperature = bytes([54])
logging.info("device or attribute not found %s")
rooms[key] = temperature
float_temp = float(temperature)
int_temp = int(float_temp)
r_server = redis.Redis('localhost')
r_server.hset(key, "temp_now", int_temp)
一旦 for 语句到达丢失的传感器,脚本将无限期挂起,只有点击 control c 才能看到问题。顺便说一句,我在绝望中放了很多异常(exception)声明:)
File "./one-wire-redis-write2.py", line 17, in <module>
temperature = s.read("temperature")
File "/usr/local/lib/python3.4/dist-packages/onewire/__init__.py", line 85, in read
return self.__getattr__(attr)
File "/usr/local/lib/python3.4/dist-packages/onewire/__init__.py", line 80, in __getattr__
if attr not in self.attrs:
< Above line 80 repeated ad nauseum >
if attr not in self.attrs:
File "/usr/local/lib/python3.4/dist-packages/onewire/__init__.py", line 107, in attrs
self._attrs = self._ow.get(self.path).split(',')
File "/usr/local/lib/python3.4/dist-packages/onewire/__init__.py", line 33, in get
return _ow.get(str(os.path.join(self._path, *path)))
KeyboardInterrupt
查看底层 onewire 模块的第 80 行 https://github.com/kipe/python-onewire/blob/master/onewire/init.py
def __getattr__(self, attr):
if attr not in self.attrs:
raise AttributeError('Attribute "%s" not found in %s.' % (attr, self.__str__()))
return self._ow.get(self.path, attr)
似乎引发了 AtributeError 但我无法捕捉到它。传感器将没有属性“温度”,因为传感器地址错误,因此不存在,因此应该引发异常任何想法我如何看到这个错误并在 except 或类似构造中使用它?
最佳答案
我最好的猜测是 attrs
属性中的某些内容导致引发 AttributeError
。 (请不要将此与第 81 行引发的 AttributeError
混淆:据我所知,该行永远不会到达。)
因为 Sensor
类有一个 __getattr__
方法,每当任何尝试访问 Sensor
实例的属性失败并返回属性错误
。当尝试读取属性 self.attrs
引发 AttributeError
时,Python 将其解释为不存在名称为 attrs
的属性。因此它调用 __getattr__
来查找 attrs
属性的值。但是,当然,__getattr__
包含读取 self.attrs
的尝试,所以整个事情会反复进行,直到堆栈溢出。
调试它的一种方法是将 onewire/__init__.py
中的 attrs
属性替换为以下内容。它捕获一个 AttributeError
,显示它的回溯并引发一个不同的异常。不同的异常阻止 Python 转到 __getattr__
来查找属性值。您需要导入 sys
和 traceback
模块:
@property
def attrs(self):
try:
if self._attrs:
return self._attrs
self._attrs = self._ow.get(self.path).split(',')
return self._attrs
except AttributeError as e:
print("AttributeError in attrs property:")
traceback.print_tb(sys.exc_info()[2])
print("AttributeError: %s" % str(e))
print("=" * 80)
raise ValueError("AttributeError in attrs property: %s" % str(e))
实际上,在 Python 3 中,您无需对 print
的三个调用和对 traceback.print_tb
的调用(以及 sys
和 traceback
imports):Python 3 检测到在 except
block 中抛出异常并将打印两个 traceback。
另一种方法是在 Onewire.get()
(onewire/__init__.py
的第 32-33 行)中捕获 AttributeError
并引发一个不同的异常(exception)。
关于python - 无法从导入的模块中捕获 python 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41086460/