Exception handling in aws-lambda functions - python

While trying to implement a DNSRequest, I also needed to do some exception handling and noticed something weird. The following code is able to catch DNS request timeouts
def lambda_handler(event, context):
hostname = "google.de"
dnsIpAddresses = event['dnsIpAddresses']
dnsResolver = dns.resolver.Resolver()
dnsResolver.lifetime = 1.0
result = {}
for dnsIpAddress in dnsIpAddresses:
dnsResolver.nameservers = [dnsIpAddress]
try:
myAnswers = dnsResolver.query(hostname, "A")
print(myAnswers)
result[dnsIpAddress] = "SUCCESS"
except dns.resolver.Timeout:
print("caught Timeout exception")
result[dnsIpAddress] = "FAILURE"
except dns.exception.DNSException:
print("caught DNSException exception")
result[dnsIpAddress] = "FAILURE"
except:
result[dnsIpAddress] = "FAILURE"
print("caught general exception")
return result
Now, if I removed the Timeout block, and assuming that a Timeout would occur, on a DNSException the message
caught DNSException exception
will never be shown.
Now, if I removed the DNSException block, and assuming that a Timeout would occur, the message
caught general exception
will never be shown.
But the Timeout extends the DNSException and the DNSException extends Exception. I had the expectation that at least the general expect block should work.
What am I missing?

In your last block try making the print line come before result[dnsIpAddress] = "FAILURE"
My guess is either there is more code than what is shown here or the line before the print statement causes a different exception.

Related

Is there a way to catch return statements from contextmanager in python?

I am trying to catch an SQLAlchemy operation result but am unsure if I can do it. Following is the code -
#contextmanager
def transaction_scope(session, close_at_exit=False):
try:
yield session
session.commit()
return True
except Exception:
session.rollback()
return False
finally:
if close_at_exit:
session.close()
with Session() as session:
with transaction_scope(session):
session.add(row)
# Catch if the above insert (add) operation is successful or not
I am inserting a record into the database. I want to get the boolean response from the transaction_scope() if my insert operation is successful or not.
You can always catch, respond to, and rethrow an exception.
with Session() as session:
with transaction_scope(session):
try:
session.add(row)
except Exception as exc:
# Oh no! It failed! Do something here...
raise
Note that the raise keyword, without an exception, can only be used in an except block and re-raises the current exception with its original stack trace intact. So we can respond to the exception and then re-raise it to allow the transaction_scope to roll back the transaction as it's supposed to.

can i raise exception from inside a function in the 'try:' block when client disconnects from the server?

im trying to build a simple server-client chatroom with python socket.
i have the following code:
def handle_connection(client):
while(1):
try:
message = receive_message()
broadcast(message["data"])
except: # for now i don't mind which exception
print("client disconnected")
def receive_message(client_socket):
try:
message_header = client_socket.recv(HEADER)
if len(message_header) == 0:
return False
message_length = int(message_header.decode("utf-8"))
message = client_socket.recv(message_length).decode("utf-8")
return {"header": message_header, "data": message}
except: # most likely will trigger when a client disconnects
return False
where receive_message() calls inside of it to client.recv(HEADER) and returns either False when there is no message, or {"header": msg_header, "data": msg} when everything is ok.
my question is: if client.recv() fails inside of receive_message() due to the client CLI closing, will it raise the exception and print "client disconnected", or not?
i did come up with the following solution i think works:
i defined a function called handle_disconnection() that handles all the content inside of the except in the code above.
def handle_connection(client_socket):
while 1:
try:
message = receive_message()
if not message:
handle_disconnection(client_socket)
break
broadcast(message["data"])
except: # client disconnected
handle_disconnection(client_socket)
break
is this a valid and/or right programming approach to the problem?
if this approach is wrong, how can i handle it correctly?
If client.recv() will raise an exception you will handle it inside of receive_message() and handle_connection() will not receive the exception.
I suggest you to identify situations when you want to control the flow with exceptions or with if-else. I think receive_message() should return a value of message or throw ConnectionError when there are connection issues. In case when there are no messages from the socket you can return None or raise NoMessagesAvailableError.
There is also a rule that tells you should catch specified exceptions, not all of them. Your code will print client disconnected when you are out of memory.

Python 3 error handling running both try and except

I am trying to implement error handling in a Python 3 script by getting the SMTPlib library to send an email when it encounters an error like this..
if value.isdigit() :
print ("Value is an integer")
else :
try:
server = smtplib.SMTP(email_server, email_port)
server.ehlo()
server.starttls()
server.login(email_login, email_pass)
server.sendmail("me#example.com", "me#example.com", message)
server.close()
sys.exit()
except:
print ("Error - Was unable to send email")
sys.exit()
This works correctly if the value is an integer, but if it is not then the email gets correctly sent but the Error message is also printed to the screen.
Why is my script running the except section as well?
sys.exit is implemented by raising an exception. When sys.exit is called after server.close, that SystemExit exception is caught.
Here is a little proof:
import sys
try:
print("hello")
sys.exit()
except:
print("exception!")
The basic rules for exception handling were not obeyed. At least except Exception: should have been used. Better except Exception as err: with err logged or printed. And the best approach is to handle only exceptions originating from the SMTP transaction guarded by try/except.

Raising exception from within except clause

I'm wondering if we can do something like the following:
We catch socket error and if the message is different than some value,
raise the exception forward to be caught on the next general except clause below?
try:
some logic to connect to a server..
except socket.error as se:
if se.messsage != '123':
raise Exception(se.message)
except exception as ex:
log.error('write something')
To do this, you need a set of try-catch blocks. Once, an exception has been caught, re-throwing the exception results in it being caught at the outer level. Try if else inside the blocks or simply nest try-except block in another one like this:
try:
try:
#...
except:
raise
except:
pass
You can simply re-raise the exception with raise without arguments:
try:
# some code
except:
if condition:
raise

Python: except EOFError: ... doesn't work

I have a try/except block that sends a message and waits for confirmation from client. If the client terminates, pickle raises an EOFError, but the code below does not catch the error and execute the graceful shut down. It instead prints stack trace. I assume it has to do with the line "except socket.error, EOFError:" - am I using the wrong syntax to handle both socket.error and EOFError there?
try:
msgs = [1]
self.sock.send(pickle.dumps(msgs))
rdy = pickle.loads(self.sock.recv(2097152))
except socket.error, EOFError:
print 'log socketmanager closing'
self.terminate()
break
In Python 2.x, the form except a, b catches an exception of type a and assign it to a variable called b. In your case this would result in EOFError being ignored. Try this instead:
...
except (socket.error, EOFError):
...
Edit: to elaborate, the new syntax in Python 3.0, and available, though not required, in 2.6+, for capturing the value of an exception is except a as b.
break is causing the error, it can only be used inside a for loop or a try/finally block, not try/except, see docs and more.

Categories

Resources