Handling a timeout error in python sockets

146,221

Solution 1

from foo import *

adds all the names without leading underscores (or only the names defined in the modules __all__ attribute) in foo into your current module.

In the above code with from socket import *, you just want to catch timeout as you've pulled timeout into your current namespace.

from socket import * pulls in the definitions of everything inside of socket, but it doesn't add socket itself.

try:
    # Socket stuff
except timeout:
    print 'caught a timeout'

Many people consider import * problematic and try to avoid it. This is because common variable names in two or more modules that are imported in this way will clobber one another.

For example, consider the following three Python files:

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

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

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

If you run yourcode.py, you'll see just the output "this is b's foo function".

For this reason I'd suggest either importing the module and using it or importing specific names from the module:

For example, your code would look like this with explicit imports:

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

It is just a tiny bit more typing, but everything's explicit and it's pretty obvious to the reader where everything comes from.

Solution 2

I had enough success just catching socket.timeout and socket.error; although socket.error can be raised for lots of reasons. Be careful.

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)

Solution 3

When you do from socket import *, the Python interpreter is loading a socket module to the current namespace. Thus you can use the module's members as if they were defined within your current Python module.

When you do import socket, a module is loaded in a separate namespace. When you are accessing its members, you should prefix them with a module name. For example, if you want to refer to a socket class, you will need to write client_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM).

As for the problem with timeout, all you need to do is to change except socket.Timeouterror: to except timeout:, since timeout class is defined inside socket module and you have imported all its members to your namespace.

Solution 4

Here is a solution I use in one of my projects.

File 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)
Share:
146,221
Greg Brown
Author by

Greg Brown

Updated on May 11, 2020

Comments

  • Greg Brown
    Greg Brown about 4 years

    I am trying to figure out how to use the try and except to handle a socket timeout.

    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
    

    The way I added the socket module was to import everything, but how do I handle exceptions in the docs it says you can use socket.timeouterror, but that doesn't work for me. Also, how would I write the try exception block if I did import socket? Can someone also explain the difference in the imports.

  • stephenbez
    stephenbez over 10 years
    I think you mean socket.timeout instead of socket.Timeouterror: docs.python.org/2/library/socket.html#socket.timeout
  • Peter Mortensen
    Peter Mortensen about 2 years
    An explanation would be in order, especially in light of the previous answers. E.g., what is the idea/gist? From the Help Center: "...always explain why the solution you're presenting is appropriate and how it works". Please respond by editing (changing) your answer, not here in comments (without "Edit:", "Update:", or similar - the answer should appear as if it was written today).