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

标签 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 语句到达丢失的传感器,脚本将无限期挂起,只有点击 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__ 来查找属性值。您需要导入 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 imports):Python 3 检测到在 except block 中抛出异常并将打印两个 traceback。

另一种方法是在 Onewire.get()(onewire/__init__.py 的第 32-33 行)中捕获 AttributeError 并引发一个不同的异常(exception)。

关于python - 无法从导入的模块中捕获 python 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41086460/

相关文章:

python - 分割所有空白后重写回文件?

python - 尽管先前已定义名称错误?

python - 漂亮的汤无法解析这个 HTML

python - 如何在没有系统特定的情况下获得 pathlib 的 unix 路径处理好东西,例如 Path.resolve() changes/tmp to/private/tmp

python - 如何在DataFrame中查找具有指定值的行

python - 替换和删除字符串中的项目

python - “Pip install”导致“error: command ' gcc ' failed with exit status 1”

python - 在 python 上安装 python-pcl 模块

python - 为什么我的深度优先搜索实现失败

python - Numpy 减法精度