无法从导入的模块中捕获python异常

时间:2016-12-11 13:01:57

标签: python python-3.x

我正在编写一个脚本,用于从单线传感器获取温度并将温度设置为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语句到达丢失的传感器,脚本将无限期挂起,只有通过点击控件c才能看到问题。顺便说一下,我在绝望中提出了不少异常陈述:)

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)

似乎引发了AtrributeError但我无法捕获它。传感器没有属性&#34;温度&#34;因为传感器地址是错误的所以不存在所以应该提出异常任何想法我怎么能看到这个错误并在一个除外或类似的结构中使用它?

1 个答案:

答案 0 :(得分:1)

我最好的猜测是attrs属性中的某些内容导致AttributeError被引发。 (请不要将此与第81行提出的AttributeError混淆:据我所知,该行永远不会到达。)

由于类Sensor具有__getattr__方法,因此每当尝试访问Sensor实例的属性失败且AttributeError时,都会调用此方法。当尝试读取属性self.attrs引发AttributeError时,Python将其解释为没有名称为attrs的属性。因此,它会调用__getattr__来查找attrs属性的值。但是,当然,__getattr__包含尝试读取self.attrs,所以整个事情一次又一次地发生,直到堆栈溢出。

调试它的一种方法是使用以下内容替换attrs中的onewire/__init__.py属性。它捕获AttributeError,显示其回溯并引发另一个异常。不同的异常阻止Python转到__getattr__来查找属性值。您需要导入systraceback模块:

    @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(以及systraceback导入)的情况下完成操作:Python 3检测到except块内正在抛出异常并将打印两个回溯。

另一种方法是在AttributeErrorOnewire.get()的第32-33行)中捕获onewire/__init__.py并引发其他异常。