2

我正在用 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

4 回答 4

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 的行为方式更加一致。

于 2010-12-29T21:45:40.740 回答
0

对于您此时想要处理的所有不同异常,我会选择带有许多 except 子句的异常,因为这些情况似乎是异常/失败的情况。

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

就知道这是否是处理这个问题的“正确”方法而言,如果两种解决方案都有效,它们都是正确的!

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

于 2010-12-29T21:33:06.613 回答
0

我认为这两种方法都没有任何问题。就个人而言,我更喜欢 try-except ,但这只是偏好。

于 2010-12-29T21:36:27.913 回答
0

有没有正确的方法

是的。

还是主观的?

不。

使用raise语句。

首先,请使用大写字母作为您的独特例外

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

于 2010-12-29T21:37:19.113 回答