web-dev-qa-db-de.com

Behandlung eines Timeout-Fehlers in Python-Sockets

Ich versuche herauszufinden, wie man den try verwendet und nur ein Socket-Timeout verarbeitet. 

from socket import *

def main():
    client_socket = socket(AF_INET,SOCK_DGRAM)
    client_socket.settimeout(1)
    server_Host = 'localhost'
    server_port = 1234
    while(True):
        client_socket.sendto('Message',(server_Host,server_port))
        try:
            reply, server_address_info = client_socket.recvfrom(1024)
            print reply
        except socket.Timeouterror:
            #more code

Ich habe das Socket-Modul hinzugefügt, um alles zu importieren, aber wie gehe ich mit Ausnahmen in den Dokumenten um, heißt es, dass Sie socket.timeouterror verwenden können, aber das funktioniert bei mir nicht. Wie würde ich auch den try-Ausnahmeblock schreiben, wenn ich import socket hätte? Kann jemand auch den Unterschied bei den Importen erklären. 

21
Greg Brown
from foo import * 

fügt alle Namen ohne führende Unterstriche (oder nur die im __all__-Attribut der Module definierten) Namen in foo in Ihr aktuelles Modul ein.

Im obigen Code mit from socket import * möchten Sie nur timeout abfangen, während Sie timeout in Ihren aktuellen Namespace eingefügt haben. 

from socket import * zieht die Definitionen von allem in socket ein, fügt jedoch socket nicht selbst hinzu.

try:
    # socketstuff
except timeout:
    print 'caught a timeout'

Viele Leute halten import * für problematisch und versuchen es zu vermeiden. Dies ist darauf zurückzuführen, dass sich die Namen allgemeiner Variablen in 2 oder mehr Modulen, die auf diese Weise importiert werden, gegenseitig blockieren.

Betrachten Sie zum Beispiel die folgenden drei Python-Dateien:

# a.py
def foo():
    print "this is a's foo function"

# b.py
def foo():
    print "this is b's foo function"

# yourcode.py
from a import *
from b import *
foo()

Wenn Sie yourcode.py ausführen, sehen Sie nur die Ausgabe "dies ist bs foo-Funktion". 

Aus diesem Grund empfehle ich, das Modul entweder zu importieren und zu verwenden oder bestimmte Namen aus dem Modul zu importieren:

Beispielsweise würde Ihr Code bei expliziten Importen folgendermaßen aussehen:

import socket
from socket import AF_INET, SOCK_DGRAM

def main():
    client_socket = socket.socket(AF_INET, SOCK_DGRAM)
    client_socket.settimeout(1)
    server_Host = 'localhost'
    server_port = 1234
    while(True):
        client_socket.sendto('Message', (server_Host, server_port))
        try:
            reply, server_address_info = client_socket.recvfrom(1024)
            print reply
        except socket.timeout:
            #more code

Nur ein bisschen mehr Tippen, aber alles ist explizit und für den Leser ist es offensichtlich, wo alles herkommt.

29
stderr

Ich hatte genug Erfolg, nur socket.timeout und socket.error; obwohl socket.error aus vielen Gründen ausgelöst werden kann. Achtung.

import socket
import logging

hostname='google.com'
port=443

try:
    sock = socket.create_connection((hostname, port), timeout=3)

except socket.timeout as err:
    logging.error(err)

except socket.error as err:
    logging.error(err)
5
ThorSummoner

Wenn Sie from socket import * tun, lädt Python ein socket-Modul in den aktuellen Namespace. So können Sie die Member des Moduls so verwenden, als wären sie in Ihrem aktuellen Python-Modul definiert.

Wenn Sie import socket ausführen, wird ein Modul in einen separaten Namespace geladen. Wenn Sie auf seine Mitglieder zugreifen, sollten Sie ihnen einen Modulnamen voranstellen. Wenn Sie sich beispielsweise auf eine socket-Klasse beziehen möchten, müssen Sie client_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) schreiben.

Was das Problem mit dem Timeout betrifft, müssen Sie nur except socket.Timeouterror: in except timeout: ändern, da die Klasse timeout im Modul socket definiert ist und Sie alle ihre Mitglieder in Ihren Namespace importiert haben.

2

Hier ist eine Lösung, die ich in einem meiner Projekte verwende.

network_utils.telnet

import socket
from timeit import default_timer as timer

def telnet(hostname, port=23, timeout=1):
    start = timer()
    connection = socket.socket()
    connection.settimeout(timeout)
    try:
        connection.connect((hostname, port))
        end = timer()
        delta = end - start
    except (socket.timeout, socket.gaierror) as error:
        logger.debug('telnet error: ', error)
        delta = None
    finally:
        connection.close()

    return {
        hostname: delta
    }

Tests

def test_telnet_is_null_when_Host_unreachable(self):
    hostname = 'unreachable'

    response = network_utils.telnet(hostname)

    self.assertDictEqual(response, {'unreachable': None})

def test_telnet_give_time_when_reachable(self):
    hostname = '127.0.0.1'

    response = network_utils.telnet(hostname, port=22)

    self.assertGreater(response[hostname], 0)
0
Édouard Lopez