I want to create a connection timeout exception using urlopen.
try:
urllib2.urlopen("http://example.com", timeout = 5)
except urllib2.URLError, e:
raise MyException("There was an error: %r" % e)
This is the code
I want to create a timeout that this code would bring an exception.
Thank You in advance.
You need to catch socket.timeout exception, check example below.
import urllib2
import socket
class MyException(Exception):
pass
try:
urllib2.urlopen("http://example.com", timeout = 1)
except socket.timeout, e:
# For Python 2.7
raise MyException("There was an error: %r" % e)
I strongly recommend using Requests library for making requests, it will make your life easier.
Related
I'm writing test script for a TCP Server in Python 3.8.
The script worka well, but now I'm tring to implemente a more efficient error catching in order to identify timeout error.
To do that I started to catch the errors and the timeout error for the socket connect.
This is my SocketConnect function:
def SocketConnect( host, port ):
global socketHandle
opResult = errorMessagesToCodes['No Error']
# Set Socket Timeout
socketHandle.settimeout(1)
logging.debug("Connect")
try:
socketHandle.connect((host, port))
except socketHandle.error as e:
opResult = errorMessagesToCodes['Socket Error']
logging.error("!!! Socket Connect FAILED: %s" % e)
return opResult
The socket handler is valid and, in order to test the timeout, I disable the server.
After one second after the connect the code goes to the except but I get this error:
socket.connect((host, port))
socket.timeout: timed out
During handling of the above exception, another exception occurred:
except socket.error as e:
AttributeError: 'socket' object has no attribute 'error'
Is there something missing?
Because I don't understand why socket object ha no attribute error. I think this is a standard error for socket interface.
Thanks in advance for the help.
UPDATE:
I tried to do a basic test (starting from a blank project): only a socket create and a socket connect (with a server not in listening mode) to simulate a timeout.
This is the code:
import socket
import logging
try:
socketHandle = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socketHandle.error as e:
logging.error("Socket Create FAILED: %s" % e)
socketHandle.settimeout(1)
try:
socketHandle.connect(('localhost', 2000))
except socketHandle.error as e:
logging.error("!!! Socket Connect FAILED: %s" % e)
The connect goes into timeout but I still get the error:
except socketHandle.error as e:
AttributeError: 'socket' object has no attribute 'error'
I really don't know what is happening.
UPDATE 2:
I made some other tests, and if I use the try-catch inside the connect function I get the error but if I use the try catch in the main a did not get any error.
Best regards,
Federico
The error is due to you redefining the module name socket; which is what contains socket.error. You are trying to access module level constants (in this case error from the socket module), from a socket object. You could also tighten the error handling to only catch a timeout. This may be needed anyhow, as it appears socket.error does not cover socket.timeout. Changing your socket name should solve the issue:
def SocketConnect(socx, host, port ):
opResult = errorMessagesToCodes['No Error']
# Set Socket Timeout
socx.settimeout(1)
logging.debug("Connect")
try:
socx.connect((host, port))
except socket.timeout as e:
opResult = errorMessagesToCodes['Socket Error']
logging.error("!!! Socket Connect FAILED: %s" % e)
return opResult
I'm using the requests module with max_retries option. I would like to catch the exceptions only related to timeouts and slow replies:
import requests
from requests.exceptions import ConnectTimeout, Timeout
URL = 'http://exmaple.com/sleep' # sleeps for 5 seconds before reply
with requests.Session() as s:
try:
a = requests.adapters.HTTPAdapter(max_retries=2)
s.mount('http://', a)
r = s.get(URL, timeout=1)
except (ConnectTimeout, Timeout) as err:
print('# {} - timeout'.format(URL))
But it looks like the underlying urllib3 library throws ReadTimeoutError and requests doesn't catch it and throws ConnectionError instead:
requests.exceptions.ConnectionError: HTTPConnectionPool(host='example.com', port=80): Max retries exceeded with url: /sleep (Caused by ReadTimeoutError("HTTPConnectionPool(host='example.com', port=80): Read timed out. (read timeout=1)"))
I don't want to add ConnectionError to the list because there are other exceptions that inherit from it so it would also catch those.
Is there a way to catch the original exception or perhaps all exceptions in the chain using traceback module.
Ideally, you should catch those other exceptions above ConnectionError and raise them if you want your program to throw an error.
class OtherException(requests.exceptions.ConnectionError):
pass
try:
raise OtherException('This is other exception.')
except OtherException as oe:
raise oe
except requests.exceptions.ConnectionError:
print('The error you want to catch')
You can use a similar contruct:
import traceback
import logging
try:
whatever()
except Exception as e:
logging.error(traceback.format_exc())
# Your actions here
This will almost catch everything except, for example, KeyboardInterrupt and SystemExit.
Catching those would make the script quite hard to quit.
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)
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
I'm using urllib.request to download files from the internet. However sometimes I get Connection Reset by Peer and I want to retry.
I tried the following, but it seems that e.errno contains socket error and not an actual errno:
while True:
try:
filename, headers = urllib.request.urlretrieve(url)
break
except IOError as e:
if e.errno != errno.ECONNRESET:
raise
except Exception as e:
raise
Any suggestions?
Well this part is not needed, first of all.
except Exception as e:
raise
And the arguments of the IOError is the type of error (socket error) and the error given to it. This error, in turn, is not the original error, but that error is in the args, so...
except IOError as e:
if e.args[1].args[0].errno != errno.ECONNRESET:
raise
Should work. I don't have a server that will reset on me, so I can't test it 100% But it works with ECONNREFUSED. :-)