2010-12-29 3 views
2

Ich schreibe eine Prozedur in Python, die auf ihrer grundlegenden Ebene mit einem Motorcontroller kommuniziert. Es ist möglich, dass der Controller Flags anzeigt, die anzeigen, dass ein Fehler aufgetreten ist. Ich versuche herauszufinden, wie ich diese Fehler am besten behandeln kann.Best Practices in Python für die Behandlung externer Ausnahmen (verwende ich raise?)

Im folgenden Beispiel gibt es drei mögliche Fehler, einen Temperaturfehler, einen Stromgrenzfehler und einen Spannungsfehler. Ich habe sie anders behandelt. Gibt es einen richtigen Weg oder ist es subjektiv?

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') 

Es scheint viel einfacher, das ganze try: fallen zu lassen. Setzen Sie einfach eine Flagge in die While-Schleife und brechen Sie ab. Schauen Sie nach der Schleife auf die Flagge und sehen Sie, ob die while-Schleife erfolgreich beendet wurde.

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. 

Aber das scheint irgendwie falsch oder nicht-Python zu verwenden einen Begriff, den ich nicht wirklich verstehe. Ist da wirklich etwas falsch? Danke und bitte bedenke, dass ich nicht CS-Hauptfach bin und seit 1982 keinen Programmierkurs belegt habe.

+0

Es scheint so, als würde man MotorFault-Klassen definieren und versuchen und außer, wie Brian und S.Lotts in ihren Antworten vorschlagen, den Weg zu gehen. Um ein wenig mehr Hintergrund für jeden Interessierten geben. Die Motorklasse wurde von jemand anderem für mich geschrieben, aber ich kann es modifizieren. Die Methoden des Motors werden tatsächlich in JSON-RPC-Nachrichten übersetzt, die an den Motorcontrollertreiber gesendet werden. Dies macht das Motorobjekt zu einem sehr einfachen Nachrichtenhandler. Aus diesem Grund sollte die Motorstatusüberprüfung nicht wirklich in das Motorobjekt gehen. Ich nehme an, ich könnte es in ein anderes Objekt einpacken, aber ich mag die Idee einer check() -Funktion. – RyanN

+0

... Der Motorcontroller-Treiber (in Java geschrieben) sendet Statusaktualisierungen über JSON-RPC zurück an mein Python-Programm, wenn sich Werte ändern. Wie Sie vielleicht vermuten, gibt es einen separaten Thread, der auf diese Nachrichten wartet und die Attribute des Motors aktualisiert. Der Code, den ich schreibe, ist ein Port von einer einfachen Version von BASIC, die auf einem Mikrocontroller lief. Der Code muss so einfach sein, dass jemand mit etwas eingeschränkten Programmierkenntnissen das Verhalten ändern kann, wenn nicht die Funktionalität. – RyanN

+0

... Ich musste hart argumentieren, dass Python geeigneter wäre als Java, also versuche ich, den prozeduralen Teil des Codes so einfach wie möglich zu halten. – RyanN

Antwort

2

Mein Ansatz, für das, was es wert ist, eine kleine Hierarchie von Ausnahmen zu definieren wäre, sagen:

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

Dann bei jedem Fehler, stellen Sie sicher, dass Ihre API eine dieser wirft. Wenn Ihre API selbst eine Ausnahme von der zugrunde liegenden Motor-API abfangen muss, umbrechen Sie diese Ausnahme in einer Ihrer eigenen Ausnahmen.

Begründung:

Ihre eigene Exception-Hierarchie ist Teil der API und dient den Aufruf von Code aus den Besonderheiten des zugrunde liegenden Motor API zu isolieren. Indem Sie eine definierte Reihe von Ausnahmen auslösen, anstatt die Ausnahmen der Motor-API zu erlauben, blenden Sie die zugrunde liegende API weiter aus. Dadurch wird es einfacher, eine andere Motor-API zu platzieren, aus welchem ​​Grund auch immer, einschließlich:

  • Sie haben eine bessere gefunden.
  • Sie möchten einige Tests mit einer verspotteten Motor-API durchführen.
  • Auch Ausnahmen (anstatt Flags) sind konsistenter mit der Art, wie sich andere Python-APIs verhalten.

    0

    Ich würde Ausnahmen mit vielen Ausnahmeklauseln für die verschiedenen Ausnahmen machen, mit denen Sie umgehen möchten Dieser Punkt, da diese Fälle Ausnahme-/Fehlerszenarien zu sein scheinen.

    Ich würde Flags nicht verwenden, um diese Szenarien darzustellen, da es mehr Felder zum Motor hinzufügen würde, die außerhalb dieses Anwendungsfalls nicht nützlich/relevant zu sein scheinen.

    Soweit zu wissen, ob es der "richtige" Weg ist, dies gut zu handhaben, wenn beide Lösungen funktionieren, sind beide korrekt!

    Hoffe, dass ich klar genug ... ;-)

    0

    ich nicht mit beiden Ansätzen sehen etwas nicht in Ordnung war. Persönlich bevorzuge ich den Versuch - außer einem, aber es ist nur Vorliebe.

    1

    Gibt es eine richtige Art und Weise

    Ja.

    oder ist es subjektiv?

    Nr

    Verwenden Sie die raise Aussage.

    Zuerst bitte CapitalLetters für Ihre einzigartige Ausnahmen

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

    Zweitens trennen die Fehlererkennung von dem Rest Ihrer Verarbeitung verwenden.

    Drittens nichts in der Ausnahmeklasse tun. Behandeln Sie das Geschäft mit Motorstopps in Ihrer Anwendung.

    Viertens, die Motorstatusprüfung gehört nicht gehören in der Anwendung Motorschleife. Dies ist alles Teil der Methodenfunktion, die motor.move_to_absolute implementiert.

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

    Fünftens sollte Ihre Anwendungsschleife so aussehen.

    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) 
    

    Der Motor sollte seine eigenen Ausnahmen auslösen. Wenn es aus irgendeinem Grund nicht möglich ist, können Sie den Motor mit einer Statusüberprüfung "wickeln". Dies ist nicht ideal, da der Motor seine eigenen Ausnahmen aufbringen sollte.

    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() 
    

    Diese Funktion kurz vor sleep aufrufen.

    +1

    -1. Das ist einfach falsch. Es gibt keinen richtigen Weg und es ist tatsächlich subjektiv. Manche Wege sind besser als andere. Aber zu sagen, immer Ausnahmen zu verwenden, ist falsch. – Falmarri

    +0

    @Falmarri: Hast du ein konkretes Gegenbeispiel?Etwas Spezifisches, das Ihren Anspruch klären würde? –

    +1

    Meine Behauptung ist, dass es subjektiv ist. Wie kann ich einen konkreten Beweis dafür haben? Es ist Codierungsstil. Da es sich um einen Motorcontroller handelt, würde ich fast sagen, dass es mit Statusflags gehen muss, da die Handhabung von Ausnahmen teuer ist. Aber ich habe keine Ahnung, wie das Projekt als Ganzes aussieht, also kann ich nicht sagen, und Sie auch nicht. – Falmarri

    Verwandte Themen