web-dev-qa-db-fra.com

Gestion d'une erreur de délai d'attente dans les sockets python

J'essaie de comprendre comment utiliser le try et sauf pour gérer un délai d'attente de socket. 

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

La façon dont j'ai ajouté le module de socket consistait à tout importer, mais comment puis-je gérer les exceptions dans la documentation? Il est dit que vous pouvez utiliser socket.timeouterror, mais cela ne fonctionne pas pour moi. De plus, comment écrirais-je le bloc d'exception try si je connaissais import socket? Quelqu'un peut-il également expliquer la différence entre les importations. 

21
Greg Brown
from foo import * 

ajoute tous les noms sans traits de soulignement (ou uniquement les noms définis dans l'attribut modules __all__) de foo dans votre module actuel.

Dans le code ci-dessus avec from socket import *, vous voulez juste attraper timeout car vous avez tiré timeout dans votre espace de noms actuel. 

from socket import * extrait les définitions de tout ce qui se trouve à l'intérieur de socket mais n'ajoute pas socket lui-même.

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

Plusieurs personnes considèrent que import * est problématique et tentent de l'éviter. Cela s'explique par le fait que les noms de variable courants dans 2 modules ou plus ainsi importés s'embrouillent.

Par exemple, considérons les trois fichiers python suivants:

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

Si vous exécutez yourcode.py, vous verrez juste le résultat "c'est la fonction foo de b". 

Pour cette raison, je suggérerais soit d'importer le module et de l'utiliser, soit d'importer des noms spécifiques à partir du module:

Par exemple, votre code ressemblerait à ceci avec des importations explicites:

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

Juste un peu plus de dactylographie mais tout est explicite et le lecteur sait très bien d'où vient tout.

29
stderr

J'ai eu assez de succès, juste catchig socket.timeout et socket.error; bien que socket.error puisse être soulevé pour de nombreuses raisons. Faites attention.

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

Lorsque vous le faites, from socket import * python charge un module socket dans l'espace de noms actuel. Ainsi, vous pouvez utiliser les membres du module comme s'ils étaient définis dans votre module python actuel.

Lorsque vous faites import socket, un module est chargé dans un espace de noms séparé. Lorsque vous accédez à ses membres, vous devez les préfixer avec un nom de module. Par exemple, si vous souhaitez faire référence à une classe socket, vous devrez écrire client_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM).

En ce qui concerne le problème de l'expiration du délai, il suffit de changer except socket.Timeouterror: en except timeout:, puisque la classe timeout est définie dans le module socket et que vous avez importé tous ses membres dans votre espace de noms.

2
Maksim Skurydzin

Voici une solution que j'utilise dans l'un de mes projets.

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
    }

Des 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