Подтвердить что ты не робот

Обработка ошибки тайм-аута в сокетах python

Я пытаюсь выяснить, как использовать try и исключать обработку тайм-аута сокета.

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

То, как я добавил модуль сокета, заключалось в том, чтобы импортировать все, но как мне обрабатывать исключения в документах, в которых говорится, что вы можете использовать socket.timeouterror, но это не работает для меня. Кроме того, как я могу написать блок исключений try, если бы я сделал import socket? Может ли кто-то объяснить разницу в импорте. Спасибо

4b9b3361

Ответ 1

from foo import * 

добавляет все имена без ведущих подчеркиваний (или только имена, определенные в атрибутах __all__ модулей) в foo в ваш текущий модуль.

В приведенном выше коде с from socket import * вы просто хотите поймать timeout, как вы потянули timeout в ваше текущее пространство имен.

from socket import * извлекает определения всего внутри socket, но не добавляет socket себя.

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

Многие считают проблему import * проблематичной и пытаются ее избежать. Это связано с тем, что общие имена переменных в двух или более модулях, которые импортируются таким образом, будут сжиматься друг с другом.

Например, рассмотрим следующие три файла python:

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

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

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

Если вы запустите yourcode.py, вы увидите только вывод "это функция foo".

По этой причине я предлагаю либо импортировать модуль и использовать его, либо импортировать определенные имена из модуля:

Например, ваш код будет выглядеть с явным импортом:

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

Просто немного больше печатать, но все явное, и это довольно очевидно для читателя, откуда все исходит.

Ответ 2

Когда вы выполняете from socket import *, python загружает модуль socket в текущее пространство имен. Таким образом, вы можете использовать члены модуля, как если бы они были определены в вашем текущем модуле python.

Когда вы выполняете import socket, модуль загружается в отдельное пространство имен. Когда вы обращаетесь к своим членам, вы должны префикс их с именем модуля. Например, если вы хотите обратиться к классу socket, вам нужно написать client_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM).

Что касается проблемы с таймаутом - все, что вам нужно сделать, это изменить except socket.Timeouterror: на except timeout:, так как класс timeout определяется внутри модуля socket, и вы импортировали все его члены в ваше пространство имен.

Ответ 3

У меня был достаточно успехов только для catchig socket.timeout и socket.error; хотя socket.error может быть поднят по многим причинам. Будьте осторожны.

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)

Ответ 4

Вот решение, которое я использую в одном из моих проектов.

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
    }

Испытания

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)