Why I got error in this tr-catch-finally block? - python

If python codes like this, no error report:
try:
sock=socket(AF_UNIX, SOCK_STREAM)
sock.settimeout(20)
sock.connect(sock_name)
test_vm_connectivity(sock)
except Exception as e:
process_output(e)
finally:
sock.settimeout(None)
sock.close()
If python codes like this, got errors, I don't know why:
for sock_name in vm_socks:
try:
sock=socket(AF_UNIX, SOCK_STREAM)
sock.settimeout(20)
sock.connect(sock_name)
test_vm_connectivity(sock)
except Exception as e:
process_output(e)
finally:
sock.settimeout(None)
sock.close()
Error:
[root#yf-mos-test-net09 tests]# python run-vhost
global name 'socket' is not defined
Traceback (most recent call last):
File "run-vhost", line 237, in <module>
test_all()
File "run-vhost", line 215, in test_all
sock.settimeout(None)
UnboundLocalError: local variable 'sock' referenced before assignment
I don't know what's different in the two codes. For code2, how to correct it, please help, thank you~

The problem actually exists (potentially at least) in your first snippet too but you haven't stumble upon it before.
The source of the problem is that the socket() call can raise an exception. If this happens and it's the first iteration, the name sock will not be defined, then you end up in the finally clause where you do reference this not-yet-existant name.
The Q&D solution is mostly to make sure sock is defined before the try/except block:
for sock_name in vm_socks:
sock = None
try:
sock=socket(AF_UNIX, SOCK_STREAM)
sock.settimeout(20)
sock.connect(sock_name)
test_vm_connectivity(sock)
except Exception as e:
process_output(e)
finally:
if sock:
sock.settimeout(None)
sock.close()

You should probably place the socket creation outside the try-except-finally block or you will access the sock in the finally block even if its creation failed and it is not assigned.
for sock_name in vm_socks:
sock=socket(AF_UNIX, SOCK_STREAM)
try:
sock.settimeout(20)
sock.connect(sock_name)
test_vm_connectivity(sock)
except Exception as e:
process_output(e)
finally:
sock.settimeout(None)
sock.close()

You are trying to access a variable that hasn't been declared is my understanding. To fix it, declare the variable before the "for" statement. I have not tested this but it should work.
Ex.
sock = "" #Declares a string without any data in the variable.

Related

Python socket connection exception

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

Python 2.7: Unable to catch exception

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?

When a socket error occur, how to get its errorcode from the exception?

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

Understanding Error Codes in Python and Using Meanful Error Names

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.

Python handling specific error codes?

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.

Categories

Resources