Catching very specific exceptions

H

Harlin Seritt

I am running the following code:

import socket

host = '9.9.45.103'
port = 10001

conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.connect((host, port))

When conn.connect() is run, there can be two different exceptions:

socket.error: (10061, 'Connection refused')
socket.error: (10060, 'Operation timed out')

How can I set up exceptions for each of these differently? Normally I
would use:

except socket.error:
code goes here...

Of course, though, these are two separate error messages under the same
error handler though. I've tried:

except socket.error, (10061, 'Connection refused'):
and
except (socket.error, 10061, 'Connection refused'):

to no avail. What do I need to do to catch each one specifically?

Thanks,

Harlin Seritt
 
A

Alex Martelli

Harlin Seritt said:
except socket.error:
code goes here...

Of course, though, these are two separate error messages under the same
error handler though. I've tried:

except socket.error, (10061, 'Connection refused'):
and
except (socket.error, 10061, 'Connection refused'):

to no avail. What do I need to do to catch each one specifically?

what I've done in such situations is

except socket.error, e:
if e.errno == 10061:
...
elif e.errno == 10060:
...
else:
raise

Not sure the code in a socket.error has attributename 'errno', but I
hope you get the general idea.


Alex
 
P

Peter Hansen

Alex said:
what I've done in such situations is

except socket.error, e:
if e.errno == 10061:
...
elif e.errno == 10060:
...
else:
raise

Not sure the code in a socket.error has attributename 'errno', but I
hope you get the general idea.

If it does not, or as a more generally applicable solution (though less
readable), one can use the args attribute:

except socket.error, e:
if e.args[0] == 10061:
...
elif e.args[0] == 10060:
...

args is just the tuple formed from the positional arguments passed to
the __init__() of the exception object when it is created, as if you did:

class Exception:
def __init__(self, *args):
self.args = args


-Peter
 
R

Roy Smith

what I've done in such situations is

except socket.error, e:
if e.errno == 10061:
...
elif e.errno == 10060:
...
else:
raise

This is not portable, however. I'm guessing you're running on Windows,
because the 10061 corresponds to:

{WSAECONNREFUSED, "Connection refused"},

in Python-2.3.4/Modules/socketmodule.c:set_error(). See
http://tinyurl.com/gth2 for more winsock error codes.

It would be nice if the socket library threw more specific exceptions, but
given that the underlying operating systems export such a wide variety of
system-level errors, it's not clear it's feasible, even if one wanted to
put the effort into it. Which brings us back to having to resort to
unportable tricks like the above to decipher the inner meaning.

But, the real question is, WHY do you want to differentiate between these?
The only reason to want to know which kind of connection failure you got is
because you want to do something different on some errors. What are you
going to do differently when you get one of these?

socket.error: (10061, 'Connection refused')
socket.error: (10060, 'Operation timed out')

Operationally, they're pretty much the same. One might guess that on a
timeout, it's worth waiting a while and trying again, but it may be worth
doing that on a refusal as well. Perhaps you caught the remote system
right after a reboot when the kernel network code is up, but the particular
service you're trying to connect to hasn't started yet? Perhaps there's
some kind of load-limiting in use? Perhaps the remote system is validating
connections by reverse DNS checks, and inconsistent DNS caches are causing
some connections to fail while others succeed? Any of these might deserve
a retry.
 
H

Harlin Seritt

Thanks for the effort on this last post, Roy. You asked what I was
hoping to do differently on these two very minutely different error
messages. What I have been trying to do for some time is to write a
ping client (for Win32 platform -- Yes, I develop almost exclusively
for Win32 environment, unfortunately) that would be a bit less buggy
than ones already written, avoid Twisted, and not even involve myself
in pynms (way overkill for what I want and need).

I am finding that with the many quirks (and really bad foundation for
Win32 APIs) that I am having to write a lot of voodoo code so to speak.
If I use a dummy port... let's say port 10001 for example... I can
attempt to connect to a machine at this port. If I get an error that
says "Connection refused", I know that the node is up but is just not
going to allow a connection. On the other hand, if I try to connect to
a node and it's really not up, I'll get a "Connection timed out" error.
In this manner I can really tell if a node is up or not (providing a
TCP/IP stack is installed there). This really what I've wanted. I am
not so concerned whether or not the node pongs back in a certain amount
of time.

Yeah normally it's annoying when people ask what you're trying to do
when you ask a specific question, but in this case it's probably
necessary to explain myself before some are willing to help out. I'm
really not interested in even negotiating a successful connection on a
specific port, but this is just a way to tell if something is up or
down (and perhaps the only real way to do it running from a Win32
platform). Thanks for the help. However, if you do have suggestions on
how to get this done better, I am more than glad to hear it!

Thanks,

Harlin Seritt
 
R

Roy Smith

Harlin Seritt said:
I am finding that with the many quirks (and really bad foundation for
Win32 APIs) that I am having to write a lot of voodoo code so to speak.

Yeah, tell me about it. My current project at work is porting our IPv6
management package (including ICMP ping) to windows; "many quirks" would be
a good way to describe it!
If I use a dummy port... let's say port 10001 for example... I can
attempt to connect to a machine at this port. If I get an error that
says "Connection refused", I know that the node is up but is just not
going to allow a connection.

Maybe. It could be that some firewall between you and the target is
blocking things. Depending on how the firewall is programmed, this may
show up as a timeout or as a connection refused (although the former would
be more common).

It's also not always a clear-cut question what "up" means. Some operating
systems can get into modes where for all intents and purposes they've
crashed, but they're still answering pings and/or actively refusing
connections.

The traditional way to tell if a node is up is to send it an ICMP echo
request, rather than trying to connect to a TCP port. You might want to
look into using that instead of trying to connect to random ports. Not
that that ICMP doesn't have its own problems :)
 
H

Harlin Seritt

Reasons why it still won't work:

* Firewall
* Unknown-modes-operating-systems-get-into

Yeah, I dont think these things can be avoided. Nonetheless, if I can
come up with some way (via help from this group--thank God!) to find if
the node is up (barring the two aforementioned reasons), I am doing
well. Maybe my standards are not so high. :-|

Nonetheless, thanks for the help and the commentary. I was beginning to
think I was losing my mind.

Harlin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top