【问题标题】:Handling a timeout error in python sockets处理python套接字中的超时错误
【发布时间】:2012-08-05 15:10:01
【问题描述】:

我试图弄清楚如何使用 try 和 except 来处理套接字超时。

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,我将如何编写try 异常块?有人还可以解释进口的区别吗?

【问题讨论】:

    标签: python sockets exception error-handling


    【解决方案1】:
    from foo import * 
    

    foo 中不带前导下划线的所有名称(或仅在模块__all__ 属性中定义的名称)添加到当前模块中。

    在上面带有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,您将只看到输出“这是 b 的 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】:

    我已经取得了足够的成功,只是赶上了socket.timeoutsocket.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)
    

    【讨论】:

      【解决方案3】:

      当您执行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 模块中定义的,并且您已将其所有成员导入您的命名空间。

      【讨论】:

        【解决方案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)
        

        【讨论】:

          猜你喜欢
          • 2016-05-14
          • 2011-07-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-04-24
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多