Circuit Python MQTT Exception Block - python

I'm using the Adafruit Circuit Python MQTT library and am trying to catch the errors being generated.
while True:
try:
# Poll the message queue
mqtt_client.loop()
except (ValueError, RuntimeError, MMQTTException) as e:
print("Failed to get data, retrying\n", e)
mqtt_client.reconnect()
# continue
time.sleep(1)
But this generates the following error:
NameError: name 'MMQTTException' is not defined
Any ideas how I should properly catch this error?
The library has the following error class. I'm guessing it needs to be exposed somehow?
class MMQTTException(Exception):
"""MiniMQTT Exception class."""
# pylint: disable=unnecessary-pass
# pass

If you did something like
import adafruit_minimqtt.adafruit_minimqtt as MQTT
in order to be able to use mqtt_client = MQTT.MQTT(...), then you need to refer to this other class similarly, as MQTT.MMQTTException.

Related

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.

Handling websocket disconnect in Python Flask server using RxPY for push based events

Context
I am using RxPY to enable sending push based events via websockets. I am using flask-sockets in a Flask server with gevent. The events class contains an rx.subject.BehaviorSubject that acts as an event publisher, while the websocket clients subscribe to changes.
Problem
I want to be able to detect when a client is disconnected so I could properly dispose the resources. The problem is when the socket is disconnected and ws.send throws an exception but it's inside the lambda.
Solution?
Is there a way to pass the exception to the parent function instead?
An alternative solution would be to detect the websocket disconnect without calling ws.send and that could be checked outside the lambda, though I could not find such method in the flask-sockets library.
#sockets.route('/ws/events')
def wsEvents(ws):
sub = None
disp = None
try:
print("socket opened")
def update_fn(x):
print(x)
ws.send(json.dumps(x))
sub = events.get_sub(None)
if sub is not None:
disp = sub.subscribe(lambda x: update_fn(x))
else:
raise Exception('Undefined sub')
while not ws.closed:
gevent.sleep(1)
pass
except Exception as e:
print(e)
finally:
print("socket closed")
if disp is not None:
disp.dispose()
I have found a workaround, detecting the socket disconnect event using a gevent timeout method like this:
while not ws.closed:
gevent.sleep(0.1)
try:
data = gevent.with_timeout(0.1, ws.receive, timeout_value="")
if data is None:
raise Exception("socket closed")
except:
break
Now it's possible to dispose the resources as the method returns None on socket disconnected event.

How to log to Kubernetes Container Log from Python process

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)

Catching exceptions raised in imported modules

I'm writing a Python program which uses the pyserial module. The program is designed to read the output from an Arduino module. I can open a serial object with:
ser = serial.Serial('/dev/cu.usbmodem641', 9600)
I can then read from it with:
line = ser.readline()
However, I want to be able to handle the exception that is thrown if I start the program without the Arduino module connected. The exception that is thrown is:
File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/serial/serialposix.py", line 292, in open
raise SerialException(msg.errno, "could not open port %s: %s" % (self._port, msg))
If I try to catch this with a general try/except block in my main program, it isn't caught. I've tried importing the SerialException from serialposix.py but that doesn't work.
Do I need to get my hands dirty with threading or is there another way of dealing with this? When the exception is thrown, I'd like to call time.sleep(5) and then just retry until the connection is available.
You can import serial.SerialException and catch that:
from serial import SerialException
try:
line = ser.readline()
except SerialException:
time.sleep(5)
The exception is a subclass of IOError, so you could use that too, but then you may be catching exceptions thrown for reasons other than the port not yet being available.

Proper syntax for executing a function only if another function is successful

I have the following code that is part of my email class that I use in my programs. Currently I am running the quit function whether or not a connection to the SMTP server was made in the connect function. I know I could put the quit function inside of the try statement after the email is sent, but I would like to figure out how to write the code to say the equivalent of "if a connection to the server is open, close it." What is the best way to write that in Python?
Thanks!
def connect(self, headers, msg):
try:
self.server.starttls()
try:
self.server.login(self.usrname,self.pswd)
try:
self.server.sendmail(self.sendfrom, self.sendto, headers + "\r\n\r\n" + msg)
except Exception as sendmailfail:
print(sendmailfail)
except Exception as emailfail:
print (emailfail)
except Exception as error:
print(error)
def quit(self):
self.server.quit()
print("The SMTP connection is closed")
first = GmailSmpt('x','y','z','zz')
x , y = first.message()
first.connect(x,y)
first.quit()
You need to finish the "Errors and Exceptions" section of the tutorial.
try:
possibly_fail()
except ...:
handle_exception()
else:
no_exceptions()
finally:
always_run_this()

Categories

Resources