Hey I'm wondering how to handle specific error codes. For example, [Errno 111] Connection refused
I want to catch this specific error in the socket module and print something.
If you want to get the error code, this seems to do the trick;
import errno
try:
socket_connection()
except socket.error as error:
if error.errno == errno.ECONNREFUSED:
print(os.strerror(error.errno))
else:
raise
You can look up errno error codes.
On Unix platforms, at least, you can do the following.
import socket, errno
try:
# Do something...
except socket.error as e:
if e.errno == errno.ECONNREFUSED:
# Handle the exception...
else:
raise
Before Python 2.6, use e.args[ 0 ] instead of e.errno.
This seems hard to do reliably/portably but perhaps something like:
import socket
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 4167))
except socket.error, e:
if 'Connection refused' in e:
print '*** Connection refused ***'
which yields:
$ python socketexception.py
*** Connection refused ***
Pretty yucky though.
I'm developing on Windows and found myself in the same predicament. But the error message always contains the error number. Using that information I just convert the exception to a string str(Exception), convert the error code I wanna check for to a string str(socket.errno.ERRORX) and check if the error code is in the exception.
Example for a connection reset exception:
except Exception as errorMessage:
if str(socket.errno.ECONNRESET) in str(errorMessage):
print("Connection reset")
#etc...
This avoids locale specific solutions but is still not platform independent unfortunately.
Related
I have a socket-connection going on and I wanna improve the exception handling and I'm stuck. Whenever I call socket.connect(server_address) with an invalid argument the program stops, but doesn't seem to raise an exception. Here is my code:
import socket
import sys
import struct
class ARToolkit():
def __init__(self):
self.x = 0
self.y = 0
self.z = 0
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.logging = False
def connect(self,server_address):
try:
self.sock.connect(server_address)
except socket.error, msg:
print "Couldnt connect with the socket-server: %s\n terminating program" % msg
sys.exit(1)
def initiate(self):
self.sock.send("start_logging")
def log(self):
self.logging = True
buf = self.sock.recv(6000)
if len(buf)>0:
nbuf = buf[len(buf)-12:len(buf)]
self.x, self.y, self.z = struct.unpack("<iii", nbuf)
def stop_logging(self):
print "Stopping logging"
self.logging = False
self.sock.close()
The class maybe looks a bit wierd but its used for receiving coordinates from another computer running ARToolKit. Anyway, the issue is at the function connect():
def connect(self,server_address):
try:
self.sock.connect(server_address)
except socket.error, msg:
print "Couldnt connect with the socket-server: %s\n terminating program" % msg
sys.exit(1)
If I call that function with a random IP-address and portnumber the whole program just stops up at the line:
self.sock.connect(server_address)
The documentation I've read states that in case of an error it will throw a socket.error-exception. I've also tried with just:
except Exception, msg:
This, if I'm not mistaken, will catch any exceptions, and still it yields no result. I would be very grateful for a helping hand. Also, is it okay to exit programs using sys.exit when an unwanted exception occurs?
Thank you
If you have chosen a random, but valid, IP address and port, socket.connect() will attempt to make a connection to that endpoint. By default, if no explicit timeout is set for the socket, it will block while doing so and eventually timeout, raising exception socket.error: [Errno 110] Connection timed out.
The default timeout on my machine is 120 seconds. Perhaps you are not waiting long enough for socket.connect() to return (or timeout)?
You can try reducing the timeout like this:
import socket
s = socket.socket()
s.settimeout(5) # 5 seconds
try:
s.connect(('123.123.123.123', 12345)) # "random" IP address and port
except socket.error, exc:
print "Caught exception socket.error : %s" % exc
Note that if a timeout is explicitly set for the socket, the exception will be socket.timeout which is derived from socket.error and will therefore be caught by the above except clause.
The problem with your last general exception is the colon placement. It needs to be after the entire exception, not after the except statement. Thus to capture all exceptions you would need to do:
except Exception,msg:
However from Python 2.6+ you should use the as statement instead of a comma like so:
except Exception as msg:
I was able to run the code fine (note you need to throw in a tuple to the connect method). If you want to specifically catch only socket errors then you would need to except the socket.error class. Like you have:
except socket.error as msg:
If you want to make sure that a tuple is entered simply add another exception loop:
except socket.error as msg:
print "Socket Error: %s" % msg
except TypeError as msg:
print "Type Error: %s" % msg
I have the following code:
def distributeMembersFile(members):
for node in members:
node = node.strip() # Strip trailing \n
if node == socket.hostname(): # No need to send the file to itself
continue
conn = None
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((node, port))
# TODO: Can possibly update the list of members here as well
s.sendall('DWLD')
s.recv(4)
except socket.error, msg:
logging.info(msg)
finally:
if s:
s.close()
Now, my question is that even though s.connect() is in a try except socket.error block, that exception is not being caught. I see the following traceback on console:
s.connect((node, port))
File "<string>", line 1, in connect
error: (111, 'Connection refused')
Interestingly, in other places I have the same try except socket.error block, and this particular (Connection refused) error is caught as:
INFO (111, 'Connection refused')
Above was printed by the logging.info function in except block. The only way I see right now to catch this exception is to use a 'bare' except, which is not considered a very good thing. Also, I found it peculiar that the error on the console is not being presented as
socket.error: (111, 'Connection refused')
Instead, it just says
error: (111. 'Connection refused')
missing the leading word 'socket'. What could be the reason behing the exception not being caught?
Codes like this:
import socket, sys
try:
address = ('127.0.0.1', 31500)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(address)
except Exception:
errType, errValue, errTraceback = sys.exc_info()
# or
# handle the Exception it throw out ?
What I want to get is the errcode like 10060 which means connection time out, thanks for any help :)
Use
except EnvironmentError as e:
print e.errno
I understand the basic try: except: finally: syntax for pythons error handling. What I don't understand is how to find the proper error names to make readable code.
For example:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.settimeout(60)
char = s.recv(1)
except socket.timeout:
pass
so if socket raises a timeout, the error is caught. How about if I am looking for a connection refused. I know the error number is 10061. Where in the documentation do I look to find a meaning full name such as timeout. Would there be a similar place to look for other python modules? I know this is a newbie question but I have been putting in error handling my my code for some time now, without actually knowing where to look for error descriptions and names.
EDIT:
Thanks for all your responses.
would
except socket.error, exception:
if exception.errno == ETIMEDOUT:
pass
achieve the same result as
except socket.timeout:
pass
To achieve what you want, you'll have to grab the raised exception, extract the error code stored into, and make some if comparisons against errno codes:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.settimeout(60)
char = s.recv(1)
except socket.error, exception:
if exception.errno == errno.ECONNREFUSED:
# this is a connection refused
# or in a more pythonic way to handle many errors:
{
errno.ECONNREFUSED : manage_connection_refused,
errno.EHOSTDOWN : manage_host_down,
#all the errors you want to catch
}.get(exception.errno, default_behaviour)()
except socket.timeout:
pass
with :
def manage_connection_refused():
print "Connection refused"
def manage_host_down():
print "Host down"
def default_behaviour():
print "error"
You will get an error with an errno, which is described in the errno documentation. 10061 is only valid for WinSock.
According to socket, socket.error values are defined in the errno module.
The error being thrown is:
error: [Errno 110] Connection timed out
I'm not sure what to except for?
try:
smtpObj = smtplib.SMTP('smtp.example.com')
smtpObj.starttls()
smtpObj.login('user','pass')
smtpObj.sendmail(sender, receivers, message)
print "Successfully sent email"
except smtplib.SMTPException('Error: unable to send email"'):
pass
except smtplib.socket.error ('Error: could not connect to server'):
pass
Thanks.
You need to provide the exception class, not an instance thereof. That is to say, the code should look like
try:
smtpObj = smtplib.SMTP('smtp.example.com')
smtpObj.starttls()
smtpObj.login('user','pass')
smtpObj.sendmail(sender, receivers, message)
print "Successfully sent email"
except smtplib.SMTPException: # Didn't make an instance.
pass
except smtplib.socket.error:
pass
The second exception, smtplib.socket.error, seems to be the applicable one to catch that error. It is usually accessed directly from the socket module import socket, socket.error.
Note that I said that was what the code "should" look like, and that's sort of an exaggeration. When using try/except, you want to include as little code as possible in the try block, especially when you are catching fairly general errors like socket.error.
I believe socket.error should work but if you post the code you're using, we can help you better. smtplib.SMTPConnectError should also be of interest.
Try something like this:
try:
server = smtplib.SMTP("something.com")
except (socket.error, smtplib.SMTPConnectError):
print >> stderr, "Error connecting"
sys.exit(-1)
OSError is the base class for smtplib.SMTPConnectError, socket.timeout, TimeoutError, etc. Therefore, you should catch OSError if you want to handle them all:
try:
...
except OSError:
...
See: https://bugs.python.org/issue20903