it-roy-ru.com

Обработка ошибки времени ожидания в сокетах Python

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

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, но это не работает для меня. Кроме того, как бы я написал блок исключения исключения, если я сделал import socket? Может кто-то также объяснить разницу в импорте. 

21
Greg Brown
from foo import * 

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

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

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

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

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

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

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

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

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

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

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

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

29
stderr

У меня было достаточно успеха, просто поймал 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)
5
ThorSummoner

Когда вы делаете 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, и вы импортировали все его члены в свое пространство имен.

2
Maksim Skurydzin

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

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)
0
Édouard Lopez