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.
Related
The bounty expires in 5 days. Answers to this question are eligible for a +50 reputation bounty.
chakmeshma wants to draw more attention to this question.
I'm writing a simple TCP relay server, which is gonna be deployed both on a Windows and a Linux machine (same code base).
Naturally there're gonna be two sockets to work with.
I would like to know which exceptions exactly do get raised for the following cases:
recv() returns when no data is available to read.
sendall() cannot complete (dispose of the whole to-send data)
Do I have to check for both errnos (socket.EWOULDBLOCK and socket.EAGAIN) when expecting to return from a non-blocking sockets recv()?
Which errno (.args[0]) do I get when sendall() fails?
Here's my code so far:
try:
socket1.setblocking(False)
socket2.setblocking(False)
while True:
try:
sock1_data = socket1.recv(1024)
if sock1_data:
socket2.sendall(sock1_data)
except socket.error as e:
if e.args[0] != socket.EAGAIN and e.args[0] != socket.EWOULDBLOCK:
raise e
try:
sock2_data = socket2.recv(1024)
if sock2_data:
socket1.sendall(sock2_data)
except socket.error as e:
if e.args[0] != socket.EAGAIN and e.args[0] != socket.EWOULDBLOCK:
raise e
except:
pass
finally:
if socket2:
socket2.close()
if socket1:
socket1.close()
My main concern is:
What socket.error.errno do I get when sendall() fails?
Lest the socket.error.errno I get from a failing sendall() is EAGAIN or EWOULDBLOCK, in which case it'd be troubling!!
Also, do I have to check for both EAGAIN and EWOULDBLOCK when handling a non-blocking recv()?
With Kubernetes Container running a Python script:
import time
while True:
try:
for i in range(10):
if i==0:
raise Exception('Exception occurred!')
except:
pass
time.sleep(1)
I would like to pass the Exception's message 'Exception occurred!' down to the Container so this error message could be seen with:
kubectl describe pod pod_id
Would it be possible?
Anything you print() will be visible in kubectl logs. (You may need to set an environment variable PYTHONUNBUFFERED=1 in your pod spec.)
Your code as you've written it will never print anything. The construct
try:
...
except:
pass
silently ignores any and all exceptions out of the try block. The bare except: even captures some system-level exceptions like SystemExit or KeyboardInterrupt; this is almost always wrong. Often you want your except blocks to be as tightly scoped as you can, and the Python tutorial on user-defined exceptions is a helpful pattern.
(The exception to this, particularly in a Kubernetes context, is that you will often want a very broad exception handler to do something like return an HTTP 500 error to a network request, rather than crashing the application.)
A better example might look like:
import time
class OneException(Exception):
pass
def iteration():
for i in range(10):
try:
if i == 1:
raise OneException("it is one")
print(i, math.sqrt(i), math.sqrt(-i))
# will work when i==0 but fail when i==2
except OneException as e:
print(i, repr(e))
# and proceed to the next iteration
if __name__ == '__main__':
while True:
# The top-level loop. We want a very broad catch here.
try:
iteration()
except Exception as e:
print('iteration failed', repr(e))
time.sleep(1)
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.
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.
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