Package: cloudAgnosticPySqsListener
[WIP] DOC TO BE UPDATED TO LATEST CHANGES
This package takes care of the boilerplate involved in listening to an SQS
queue, as well as sending messages to a queue.  Works with python 2.7 & 3.6+.Publish new version(if not yet done) Configure your ~/.pypirc :https://packaging.python.org/en/latest/specifications/pypirc/Install build tool :python3-mpip install--upgradebuild && python3-mpip install--upgradetwineUpdate version number in setup.pypython3-mbuild && python3-mtwine upload--repositorypypi dist/*Installationpip install cloudAgnosticPySqsListenerListening to a queueUsing the listener is very straightforward - just inherit from theSqsListenerclass and implement thehandle_message()method.
The queue will be created at runtime if it doesn’t already exist.
You can also specify an error queue to automatically push any errors to.Here is a basic code sample:Standard Listenerfrom sqs_listener import SqsListener

class MyListener(SqsListener):
    def handle_message(self, body, attributes, messages_attributes):
        run_my_function(body['param1'], body['param2'])

listener = MyListener('my-message-queue', error_queue='my-error-queue', region_name='us-east-1')
listener.listen()Error Listenerfrom sqs_listener import SqsListener
class MyErrorListener(SqsListener):
    def handle_message(self, body, attributes, messages_attributes):
        save_to_log(body['exception_type'], body['error_message']

error_listener = MyErrorListener('my-error-queue')
error_listener.listen()The options available askwargsare as follows:error_queue (str) - name of queue to push errors.force_delete (boolean) - delete the message received from the queue, whether or not the handler function is successful.  By default the message is deleted only if the handler function returns with no exceptionsinterval (int) - number of seconds in between polls. Set to 60 by defaultvisibility_timeout (str) - Number of seconds the message will be invisible (‘in flight’) after being read.  After this time interval it reappear in the queue if it wasn’t deleted in the meantime.  Set to ‘600’ (10 minutes) by defaulterror_visibility_timeout (str) - Same as previous argument, for the error queue.  Applicable only if theerror_queueargument is set, and the queue doesn’t already exist.wait_time (int) - number of seconds to wait for a message to arrive (for long polling). Set to 0 by default to provide short polling.max_number_of_messages (int) - Max number of messages to receive from the queue. Set to 1 by default, max is 10message_attribute_names (list) - message attributes by which to filter messagesattribute_names (list) - attributes by which to filter messages (see boto docs for difference between these two)region_name (str) - AWS region name (defaults tous-east-1)queue_url (str) - overridesqueueparameter. Mostly useful for getting aroundthis bugin the boto librarydeserializer (function str -> dict) - Deserialization function that will be used to parse the message body. Set to python’sjson.loadsby default.aws_access_key, aws_secret_key (str) - for manually providing AWS credentialsregion_name (str), endpoint_name (str) - to manually providing SQS endpoint region & urlrun_while_idle (Callable) - a function that will be called on every “empty” run, as a heartbeat, to make sure it’s still runingRunning as a DaemonTypically, in a production environment, you’ll want to listen to an SQS queue with a daemonized process.
The simplest way to do this is by running the listener in a detached process.  On a typical Linux distribution it might look   like this:nohup python my_listener.py > listener.log &And saving the resulting process id for later (for stopping the listener via thekillcommand).A more complete implementation can be achieved easily by inheriting from the package’sDaemonclass and overriding therun()method.The sample_daemon.py file in the source root folder provides a clear example for achieving this.  Using this example,
you can run the listener as a daemon with the commandpython sample_daemon.py start.  Similarly, the commandpython sample_daemon.py stopwill stop the process.  You’ll most likely need to run the start script usingsudo.LoggingThe listener and launcher instances push all their messages to aloggerinstance, called ‘sqs_listener’.
In order to view the messages, the logger needs to be redirected tostdoutor to a log file.For instance:logger = logging.getLogger('sqs_listener')
logger.setLevel(logging.INFO)

sh = logging.StreamHandler()

formatstr = '[%(asctime)s - %(name)s - %(levelname)s]  %(message)s'
formatter = logging.Formatter(formatstr)

sh.setFormatter(formatter)
logger.addHandler(sh)Or to a log file:logger = logging.getLogger('sqs_listener')
logger.setLevel(logging.INFO)

sh = logging.FileHandler('mylog.log')
sh.setLevel(logging.INFO)

formatstr = '[%(asctime)s - %(name)s - %(levelname)s]  %(message)s'
formatter = logging.Formatter(formatstr)

sh.setFormatter(formatter)
logger.addHandler(sh)Sending messagesIn order to send a message, instantiate anSqsLauncherwith the name of the queue.  By default an exception will
be raised if the queue doesn’t exist, but it can be created automatically if thecreate_queueparameter is
set to true.  In such a case, there’s also an option to set the newly created queue’sVisibilityTimeoutvia the
third parameter. It is possible to provide aserializerfunction if custom types need to be sent. This function
expects a dict object and should return a string. If not provided, python’sjson.dumpsis used by default.After instantiation, use thelaunch_message()method to send the message.  The message body should be adict,
and additional kwargs can be specified as stated in theSQS docs.
The method returns the response from SQS.Launcher Examplefrom sqs_launcher import SqsLauncher

launcher = SqsLauncher('my-queue')
response = launcher.launch_message({'param1': 'hello', 'param2': 'world'})Important NotesFor both the main queue and the error queue, if the queue doesn’t
exist (in the specified region), it will be created at runtime.The error queue receives only two values in the message body:exception_typeanderror_message. Both are of typestrIf the function that the listener executes involves connecting to a database, you should explicitly close the connection at the end of the function.  Otherwise, you’re likely to get an error like this:OperationalError(2006, 'MySQL server has gone away')Either the queue name or the queue url should be provided. When both are provided the queue url is used and the queue name is ignored.ContributingFork the repo and make a pull request.