Python中用于处理外部异常的最佳实践(我是否使用raise?)

时间:2010-12-29 21:23:00

标签: python robotics

我正在用Python编写一个程序,它的基本级别与电机控制器通信。控制器可以抛出表示发生错误的标志。我想弄清楚如何最好地处理这些错误。

在下面的示例中,有三种可能的错误,温度故障,电流限制故障和电压故障。我对他们的处理方式不同了。有正确的方法还是主观的?

class motor_fault(Exception):
    def __init__(self,error):
        motor.move_at = 0  #Stop motor
        self.error = error
    def __str__(self):
        return repr(self.value)

motor.velocity_limit = motor.slow
motor.velocity_limit_enable = True
try:
    motor.move_to_absolute = motor.instrument_pos
    while motor.in_position == 0:
        if motor.current_limit == 1:
            motor.move_at = 0 #Stop motor
            print('Motor current error')
            break
        if motor.temp_fault == 1: raise motor_fault('Temperature Fault')
        if motor.voltage_fault == 1: raise voltage_fault:
        time.sleep(0.5)
    else:
        print('reached desired instrument position with no faults')
except motor_temp_fault as e:
    #Not sure what I'd do here...
    print('My exception occurred, value:', e.error)
    pass
except:
    motor.move_at = 0 #Stop motor just in case
    print(' some other fault, probably voltage')
else:
    print (' this is only printed if there were no errors')
finally:
    print ('this is printed regardless of how the try exits')

放弃整个try:似乎要简单得多。只需在while循环中设置一个标志并中断。在循环之后,查看标志并查看while循环是否成功退出。

fault = False
while motor.in_position == 0:
    if motor.current_limit == 1:
        fault = 'Motor current error'
        break
    if motor.temp_fault == 1:
        fault = 'Motor temperature error'
        break
    if motor.voltage_fault == 1:
        fault = 'Motor voltage error'
        break
    time.sleep(0.5)
else:
    print('reached waterline with no faults')
if fault:
    motor.move_at = 0 #Stop motor
    print(fault)
    # Now look at the fault string to determine the next course of action.

但是,使用我并不真正理解的术语,似乎有些错误或非pythonic。这有什么不妥吗? 谢谢,请记住,我不是CS专业,自1982年以来我没有参加过编程课程。

4 个答案:

答案 0 :(得分:2)

我的方法,就是它的价值,是定义一个小的异常层次结构,比如说:

class MotorFaultError(Exception) # top level exception
class MotorTempFault(MotorFaultError)
class MotorVoltageFault(MotorFaultError)
# etc

然后,在出现任何错误时,请确保您的API会抛出其中一个错误。如果您的API本身必须从基础电机API捕获异常,请将该异常包装在您自己的异常中。

理由:

您自己的异常层次结构是API的一部分,用于将调用代码与基础电机API的细节隔离开来。通过抛出一组定义的异常,而不是允许电机API的异常冒泡,您进一步隐藏了底层API。这样做可以更容易地放弃另一个电机API,无论出于何种原因,包括:

  • 你找到了一个更好的。
  • 您希望使用模拟电机API进行一些测试。

此外,异常(而不是标志)与其他Python API的行为方式更加一致。

答案 1 :(得分:1)

  

有没有正确的方法

  

还是主观的?

没有

使用raise声明。

首先,请使用CapitalLetters获取您的唯一例外

class Motor_Fault( Exception ): pass
class Temperature_Fault( Motor_Fault ): pass
class Voltage_Fault( Motor_Fault ): pass
class Current_Fault( Motor_Fault ): pass

其次,将错误检测与其余处理分开。

第三,不要在异常类中做任何事情。在您的应用程序中处理电机停止业务。

第四,电机状态检查属于应用程序的电机回路。这是实现motor.move_to_absolute的方法函数的所有部分。

    if motor.current_limit == 1: raise Current_Fault()
    if motor.temp_fault == 1: raise Temperature_Fault()
    if motor.voltage_fault == 1: raise Voltage_Fault()

第五,你的应用程序循环应该是这样的。

motor.velocity_limit = motor.slow
motor.velocity_limit_enable = True
try:
    motor.move_to_absolute = motor.instrument_pos
    while motor.in_position == 0:
        time.sleep(0.5)
    print('reached desired instrument position with no faults')
except Motor_Fault, e:
    motor.move_at = 0 #Stop motor
    print(fault)

电机应该提出它自己的例外情况。如果由于某种原因,它不能,那么你可以通过一些状态检查“包裹”电机。这并不理想,因为电机应该提高它自己的例外。

 def check():
    if motor.current_limit == 1: raise Current_Fault()
    if motor.temp_fault == 1: raise Temperature_Fault()
    if motor.voltage_fault == 1: raise Voltage_Fault()

sleep之前调用此函数。

答案 2 :(得分:0)

我会针对你想要处理的所有不同异常的许多例外条款进行例外处理,因为这些情况似乎是异常/失败情况。

我不会使用标志来表示这些场景,因为它会向电机添加更多字段,这些字段在此用例之外似乎没有用处/相关。

至于知道这是否是“正确”处理这种方法的方法,如果两种解决方案都有效,那么它们都是正确的!

希望我足够清楚......; - )

答案 3 :(得分:0)

我认为这两种方法都没有错。就个人而言,我更喜欢尝试 - 除了一个,但它只是偏好。