Python: how to distinguish between socket error and timeout? - python

I'm having the following code:
try:
while 1:
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.settimeout(5);
s.connect((HOST,PORT))
print("before send")
#time.sleep(10);
#s.sendall('GET / HTTP/1.1\r\nConnection: Keep-Alive\r\nHost: www.google.lt\r\n\r\n')
data=s.recv(52)
print("after send");
s.close()
if string.find(data,"HTTP/1.1 200 OK") == -1:
print("Lost Connection")
print(data)
time.sleep(2)
except KeyboardInterrupt:
print("CTRL C occured")
except socket.error:
print("socket error occured: ")
except socket.timeout:
print("timeout error")
I have commented the sendall function to test how recv generates timeout exception.
But the problem is that i get socket.error exception.
If i change the last lines of code to:
except socket.timeout:
print("timeout error")
except socket.error:
print("socket error occured: ")
Then i get socket.timeout exception.
So what exception is really generated?

socket.timeout is a subclass of socket.error. Really it's socket.timeout. When you catch a socket.error first, you catch a more general case.
>>> issubclass(socket.timeout, socket.error)
True
This code is correct:
except socket.timeout:
print("timeout error")
except socket.error:
print("socket error occured: ")
Try to catch specifically socket.timeout, then other socket.errors.

Related

How do I check if I connected to the server? Python Sockets

I haven't tested that yet, but if the connection will not be executed, will this last sentence be printed?
def connect_to():
print(f"[*] Connecting to {receiver_ip}:{receiver_port}")
socket.connect((receiver_ip, receiver_port))
print(f"[+] Connected")
How can I check if I connected properly and make a proper if statement?
When a socket fails to connect, it will raise a socket.error exception. You can catch that specific error using some error handling techniques in Python.
import socket
def connect(ip, port):
s = socket.socket()
try:
print(f"Connecting to {ip}:{port}")
s.connect((ip, port))
except socket.error as msg:
print(f"Failed to connect: {msg}")
else:
print(f"Successfully connected to {ip}:{port}")
How can I check if I connected properly and make a proper if statement?
The except block will be executed if the specified error is caught in the try block. On the other hand, the else block will be executed when no errors were raised or handled. You can view the except block as "if error" and the else block as "if not error".
Alternatively, you can catch an error and re-raise it with your custom message.
import socket
def connect(ip, port):
s = socket.socket()
try:
print(f"Connecting to {ip}:{port}")
s.connect((ip, port))
except socket.error as msg:
raise socket.error(f"Failed to connect: {msg}")
print(f"Successfully connected to {ip}:{port}")
By catching and re-raising, you don't have to use the else block anymore.
Use try except to catch the errors and if the connection is successful

Unestablished connection and content manager

The following function allows to use the with-statment and the a pop connection. But if the connection is not established, the quit() in finally will raise an exception. How can this be fixed?
#contextmanager
def pop_connect(server, user, password, timeout, use_SSL=False):
try:
pop = poplib.POP3_SSL if use_SSL else poplib.POP3
pop_conn = pop(server, timeout=timeout)
pop_conn.pass_(password)
yield pop_conn
except poplib.error_proto as pop_error:
print('Authentication for receiving emails failed:{}'.format(pop_error))
except OSError as os_error:
print('Name resolution or connection failed:{}'.format(os_error))
finally:
pop_conn.quit()
I suppose you can put your pop_conn.quit() in a try: with pass as corresponding except action:
finally:
try:
pop_conn.quit()
except <WhaterverException>:
pass
The solution is to rethrow the exceptions in the handlers. The contextmanager than does not except the yield:
#contextmanager
def pop_connect(server, user, password, timeout, use_SSL=False):
try:
pop_conn = poplib.POP3_SSL(server,timeout=timeout) if use_SSL else poplib.POP3_SSL(server,timeout=timeout)
pop_conn.user(user)
pop_conn.pass_(password)
yield pop_conn
except poplib.error_proto as pop_error:
print('Receiving mail failed:{}'.format(pop_error))
raise
except OSError as os_error:
print('Name resolution or connection failed:{}'.format(os_error))
raise
finally:
try:
pop_conn.quit()
except UnboundLocalError:
pass

Catch "Could not open connection to gateway" in sshtunnel.py

Every now and then setting up a tunnel using sshtunnel.py fails because the gateway (ssh_host) complains the first time I connect to it. I would like to give it a few retries before giving up:
for attempt in range(5):
try:
forwarder.start()
except Exception, e:
print 'Error (trying again in five seconds):\n' + format(e.message))
time.sleep(5)
else:
break
else:
print 'Failed to setup a connection to the gateway'
sys.exit(1)
However, the error is not 'detected'. I took a peek in the sshtunnel.py code and found that the following code catches the related Paramiko exception:
except paramiko.ssh_exception.AuthenticationException:
self.logger.error('Could not open connection to gateway')
return
How do I catch this in my try:?
An SSHTunnel.py project member advised me to add forwarder._check_is_started() to my code:
for attempt in range(5):
try:
forwarder.start()
forwarder._check_is_started()
except BaseSSHTunnelForwarderError as e:
print 'Error (trying again in five seconds):\n' + format(e.message))
time.sleep(5)
else:
break
else:
print 'Failed to setup a connection to the gateway'
sys.exit(1)

Checking for Timeout Error in python

So I have a pretty generic logging statement after a request:
try:
r = requests.get(testUrl, timeout=10.0)
except Exception, err:
logger.error({"message": err.message})
This works great for everything I've thrown at it except TimeoutError. When the request times out the err I get back is a tuple that it tries and fails to serialize.
My question is how do I catch just this one type of error? For starters TimeoutError is not something I have access to. I have tried adding from exceptions import * but with no luck. I've also tried importing OSError because the docs say TimeoutError is a subclass, but I was unable to access TimeoutError after importing OSError.
TimeoutError docs
I plan to either list my exceptions in order:
except TimeoutError, err:
#handle this specific error
except Exception, err:
#handle all other errors
or just check for type:
except Exception, err:
if isinstance(err, TimeoutError):
#handle specific error
#handle all other errors
Python 2.7.3 & Django 1.5
You can handle requests.Timeout exception:
try:
r = requests.get(testUrl, timeout=10.0)
except requests.Timeout as err:
logger.error({"message": err.message})
except requests.RequestException as err:
# handle other errors
Example:
>>> import requests
>>> url = "http://httpbin.org/delay/2"
>>> try:
... r = requests.get(url, timeout=1)
... except requests.Timeout as err:
... print(err.message)
...
HTTPConnectionPool(host='httpbin.org', port=80): Read timed out. (read timeout=1)

Create Socket Errors on Purpose / Python Script

I want to create socket errors (By doing things, obviously) but I've no idea how I should test if my script handles errors properly (If it dectes them.)
Currently, my code is this:
except socket.error as err:
print "Connection lost, waiting..."
time.sleep(5)
In theory, it should handle all the socket errors, print and then sleep (It's a part of a while loop.).
Any idea of how can I test it to see how it handles errors?
Use the raise statement:
try:
raise socket.error
except socket.error as err:
print "Connection lost, waiting..."
time.sleep(5)
Yet another example:
try:
raise AttributeError
except AttributeError:
print 'Sorry'
#Sorry
Also take a look at here and here

Categories