2016-07-23 26 views
0

Ich arbeite an einem grundlegenden Socket-Client-Programm in Python und ich bin nicht ganz sicher, wie mit Ausnahmen umzugehen. Dies ist, was ich jetzt habe bis:Python-Socket-Programmierung - Ausnahmebehandlung

TCP_IP  = '..............' 
TCP_PORT = 4950 
MESSAGE  = "o3" 
BUFFER_SIZE = 2048 
data  = "" 

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 

s.settimeout(5.0) 

try: 
    s.connect((TCP_IP, TCP_PORT)) 
except socket.error: 
    #write error code to file 
    s.close() 

try: 
    s.sendall(MESSAGE) 
except socket.error: 
    #write to file or whatever 
    s.close() 

try: 
    data = s.recv(BUFFER_SIZE) 
except socket.error: 
    #write to file or whatever 
    s.close() 

finally: 
    s.close() 

Der Code funktioniert, wie ich will, aber ich bin nicht sicher, ob ich sollte Nest try/catch-Blöcke oder nicht? Sollte ich auch socket.socket in try/catch-Block setzen?

Zweite Frage, was wird s.settimeout() in meinem Fall tun? Soweit ich die Dokumentation verstanden habe, wird nach 5 Sekunden eine Ausnahme ausgelöst, aber wofür? Nur connect oder wird es das gleiche für sendall und recv tun?

Antwort

2

Da Sie genau die gleichen Aktionen in allen Ausnahme Blöcke tun und die gleiche socket.error Ausnahme abfangen, können Sie s.connect, s.sendall und s.recv im gleichen try: Block setzen. Wie so:

try: 
    s.connect((TCP_IP, TCP_PORT)) 
    s.sendall(MESSAGE) 
    data = s.recv(BUFFER_SIZE) 
except socket.error: 
    #write error code to file 
finally: 
    s.close() 

Beachten Sie, dass seit s.close ist auch im finally Abschnitt in Ihrem Beispiel, es wird immer aufgerufen, auch nachdem eine Ausnahme aufgetreten ist. Es würde also zu einer weiteren Ausnahme kommen, wenn Sie versuchen, einen bereits geschlossenen Socket zu schließen. Indem Sie es nicht in den except Block und nur in finally setzen, können Sie diese Situation vermeiden.

Wenn Sie beabsichtigen, jeden Fehler auf eine andere Weise zu behandeln, können Sie sie getrennt wie Sie bereits haben. Aber stellen Sie sicher, break/return am Ende der Ausnahme blockieren, so dass Sie nicht versuchen, die nächste. Es ist so in der socket examples, mit einer continue in der Schleife getan.

Eine Verschachtelung würde helfen, wenn Sie im Ausnahmeblock etwas anderes machen wollten. Aber wenn nicht, würden Sie den Block except jedes Mal wiederholen. Und wenn Sie etwas anderes machen wollten, wenn Sie die verschachtelten try s verlassen, würden Sie nicht sicher sein, welche Stufe es abgeschlossen hat oder eine Ausnahme ausgelöst hat - würde Flag-Werte usw. verwenden müssen, um das nur zu verfolgen. So für Ihr Beispiel aus dem gleichen Fehlerbehandlung Code, zumindest, etwas zu tun, wie dies in Ihrem except Block:

except socket.error as e: 
    socket_error_handler(e, s) 

def socket_error_handler(exception, socket): 
    #write error code to file 
    etc. 

Soll ich socket.socket in try/catch-Block zu?

Sie tun das in den oben verlinkten Beispielen.

Abgesehen von der Protokollierung sollten Sie nicht in jeder Phase die gleiche Ausnahmebehandlung durchführen. Wahrscheinlich müssen diese separat behandelt werden.

Teil 2:

s.settimeout(5.0) das Timeout für jeden Sockel Betrieb setzt, nicht nur die erste Verbindung. Impliziert auch, dass es in blocking mode ist.

+0

Vielen Dank für diese großartige Antwort! Noch eine Frage, was passiert, wenn ich die Originalversion verwende (try/catch Blöcke nacheinander) und Ausnahme wird bei socket.connect() abgefangen .. Ich denke, alle Socket-Operationen werden ausgeführt, was nicht gut ist? –