OLD | NEW |
(Empty) | |
| 1 .. _sqs_tut: |
| 2 |
| 3 ======================================= |
| 4 An Introduction to boto's SQS interface |
| 5 ======================================= |
| 6 |
| 7 This tutorial focuses on the boto interface to the Simple Queue Service |
| 8 from Amazon Web Services. This tutorial assumes that you have boto already |
| 9 downloaded and installed. |
| 10 |
| 11 Creating a Connection |
| 12 --------------------- |
| 13 The first step in accessing SQS is to create a connection to the service. |
| 14 The recommended method of doing this is as follows:: |
| 15 |
| 16 >>> import boto.sqs |
| 17 >>> conn = boto.sqs.connect_to_region( |
| 18 ... "us-east-1", |
| 19 ... aws_access_key_id='<aws access key'>, |
| 20 ... aws_secret_access_key='<aws secret key>') |
| 21 |
| 22 At this point the variable conn will point to an SQSConnection object in the |
| 23 US-EAST-1 region. Bear in mind that just as any other AWS service, SQS is |
| 24 region-specific. In this example, the AWS access key and AWS secret key are |
| 25 passed in to the method explicitely. Alternatively, you can set the environment |
| 26 variables: |
| 27 |
| 28 * ``AWS_ACCESS_KEY_ID`` - Your AWS Access Key ID |
| 29 * ``AWS_SECRET_ACCESS_KEY`` - Your AWS Secret Access Key |
| 30 |
| 31 and then simply call:: |
| 32 |
| 33 >>> import boto.sqs |
| 34 >>> conn = boto.sqs.connect_to_region("us-east-1") |
| 35 |
| 36 In either case, conn will point to an SQSConnection object which we will |
| 37 use throughout the remainder of this tutorial. |
| 38 |
| 39 Creating a Queue |
| 40 ---------------- |
| 41 Once you have a connection established with SQS, you will probably want to |
| 42 create a queue. In its simplest form, that can be accomplished as follows:: |
| 43 |
| 44 >>> q = conn.create_queue('myqueue') |
| 45 |
| 46 The create_queue method will create (and return) the requested queue if it does
not |
| 47 exist or will return the existing queue if it does. There is an |
| 48 optional parameter to create_queue called visibility_timeout. This basically |
| 49 controls how long a message will remain invisible to other queue readers |
| 50 once it has been read (see SQS documentation for more detailed explanation). |
| 51 If this is not explicitly specified the queue will be created with whatever |
| 52 default value SQS provides (currently 30 seconds). If you would like to |
| 53 specify another value, you could do so like this:: |
| 54 |
| 55 >>> q = conn.create_queue('myqueue', 120) |
| 56 |
| 57 This would establish a default visibility timeout for this queue of 120 |
| 58 seconds. As you will see later on, this default value for the queue can |
| 59 also be overridden each time a message is read from the queue. If you want |
| 60 to check what the default visibility timeout is for a queue:: |
| 61 |
| 62 >>> q.get_timeout() |
| 63 30 |
| 64 |
| 65 Listing all Queues |
| 66 ------------------ |
| 67 |
| 68 To retrieve a list of the queues for your account in the current region:: |
| 69 |
| 70 >>> conn.get_all_queues() |
| 71 [ |
| 72 Queue(https://queue.amazonaws.com/411358162645/myqueue), |
| 73 Queue(https://queue.amazonaws.com/411358162645/another_queue), |
| 74 Queue(https://queue.amazonaws.com/411358162645/another_queue2) |
| 75 ] |
| 76 |
| 77 This will leave you with a list of all of your :py:class:`boto.sqs.queue.Queue` |
| 78 instances. Alternatively, if you wanted to only list the queues that started |
| 79 with ``'another'``:: |
| 80 |
| 81 >>> conn.get_all_queues(prefix='another') |
| 82 [ |
| 83 Queue(https://queue.amazonaws.com/411358162645/another_queue), |
| 84 Queue(https://queue.amazonaws.com/411358162645/another_queue2) |
| 85 ] |
| 86 |
| 87 Getting a Queue (by name) |
| 88 ------------------------- |
| 89 If you wish to explicitly retrieve an existing queue and the name of the queue i
s known, |
| 90 you can retrieve the queue as follows:: |
| 91 |
| 92 >>> my_queue = conn.get_queue('myqueue') |
| 93 Queue(https://queue.amazonaws.com/411358162645/myqueue) |
| 94 |
| 95 This leaves you with a single :py:class:`boto.sqs.queue.Queue`, which abstracts |
| 96 the SQS Queue named 'myqueue'. |
| 97 |
| 98 Writing Messages |
| 99 ---------------- |
| 100 Once you have a queue setup, presumably you will want to write some messages |
| 101 to it. SQS doesn't care what kind of information you store in your messages |
| 102 or what format you use to store it. As long as the amount of data per |
| 103 message is less than or equal to 256Kb, SQS won't complain. |
| 104 |
| 105 So, first we need to create a Message object:: |
| 106 |
| 107 >>> from boto.sqs.message import Message |
| 108 >>> m = Message() |
| 109 >>> m.set_body('This is my first message.') |
| 110 >>> status = q.write(m) |
| 111 |
| 112 The write method returns a True if everything went well. If the write |
| 113 didn't succeed it will either return a False (meaning SQS simply chose |
| 114 not to write the message for some reason) or an exception if there was |
| 115 some sort of problem with the request. |
| 116 |
| 117 Writing Messages (Custom Format) |
| 118 -------------------------------- |
| 119 The technique above will work only if you use boto's default Message payload for
mat; |
| 120 however, you may have a lot of specific requirements around the format of |
| 121 the message data. For example, you may want to store one big string or you migh
t |
| 122 want to store something that looks more like RFC822 messages or you might want |
| 123 to store a binary payload such as pickled Python objects. |
| 124 |
| 125 The way boto deals with this issue is to define a simple Message object that |
| 126 treats the message data as one big string which you can set and get. If that |
| 127 Message object meets your needs, you're good to go. However, if you need to |
| 128 incorporate different behavior in your message or handle different types of |
| 129 data you can create your own Message class. You just need to register that |
| 130 class with the boto queue object so that it knows that, when you read a message
from the |
| 131 queue, it should create one of your message objects rather than the |
| 132 default boto Message object. To register your message class, you would:: |
| 133 |
| 134 >>> import MyMessage |
| 135 >>> q.set_message_class(MyMessage) |
| 136 >>> m = MyMessage() |
| 137 >>> m.set_body('This is my first message.') |
| 138 >>> status = q.write(m) |
| 139 |
| 140 where MyMessage is the class definition for your message class. Your |
| 141 message class should subclass the boto Message because there is a small |
| 142 bit of Python magic happening in the __setattr__ method of the boto Message |
| 143 class. |
| 144 |
| 145 Reading Messages |
| 146 ---------------- |
| 147 |
| 148 So, now we have a message in our queue. How would we go about reading it? |
| 149 Here's one way: |
| 150 |
| 151 >>> rs = q.get_messages() |
| 152 >>> len(rs) |
| 153 1 |
| 154 >>> m = rs[0] |
| 155 >>> m.get_body() |
| 156 u'This is my first message' |
| 157 |
| 158 The get_messages method also returns a ResultSet object as described |
| 159 above. In addition to the special attributes that we already talked |
| 160 about the ResultSet object also contains any results returned by the |
| 161 request. To get at the results you can treat the ResultSet as a |
| 162 sequence object (e.g. a list). We can check the length (how many results) |
| 163 and access particular items within the list using the slice notation |
| 164 familiar to Python programmers. |
| 165 |
| 166 At this point, we have read the message from the queue and SQS will make |
| 167 sure that this message remains invisible to other readers of the queue |
| 168 until the visibility timeout period for the queue expires. If you delete |
| 169 the message before the timeout period expires then no one else will ever see |
| 170 the message again. However, if you don't delete it (maybe because your reader c
rashed |
| 171 or failed in some way, for example) it will magically reappear in my queue |
| 172 for someone else to read. If you aren't happy with the default visibility |
| 173 timeout defined for the queue, you can override it when you read a message: |
| 174 |
| 175 >>> q.get_messages(visibility_timeout=60) |
| 176 |
| 177 This means that regardless of what the default visibility timeout is for |
| 178 the queue, this message will remain invisible to other readers for 60 |
| 179 seconds. |
| 180 |
| 181 The get_messages method can also return more than a single message. By |
| 182 passing a num_messages parameter (defaults to 1) you can control the maximum |
| 183 number of messages that will be returned by the method. To show this |
| 184 feature off, first let's load up a few more messages. |
| 185 |
| 186 >>> for i in range(1, 11): |
| 187 ... m = Message() |
| 188 ... m.set_body('This is message %d' % i) |
| 189 ... q.write(m) |
| 190 ... |
| 191 >>> rs = q.get_messages(10) |
| 192 >>> len(rs) |
| 193 10 |
| 194 |
| 195 Don't be alarmed if the length of the result set returned by the get_messages |
| 196 call is less than 10. Sometimes it takes some time for new messages to become |
| 197 visible in the queue. Give it a minute or two and they will all show up. |
| 198 |
| 199 If you want a slightly simpler way to read messages from a queue, you |
| 200 can use the read method. It will either return the message read or |
| 201 it will return None if no messages were available. You can also pass |
| 202 a visibility_timeout parameter to read, if you desire: |
| 203 |
| 204 >>> m = q.read(60) |
| 205 >>> m.get_body() |
| 206 u'This is my first message' |
| 207 |
| 208 Deleting Messages and Queues |
| 209 ---------------------------- |
| 210 As stated above, messages are never deleted by the queue unless explicitly told
to do so. |
| 211 To remove a message from a queue: |
| 212 |
| 213 >>> q.delete_message(m) |
| 214 [] |
| 215 |
| 216 If I want to delete the entire queue, I would use: |
| 217 |
| 218 >>> conn.delete_queue(q) |
| 219 |
| 220 However, and this is a good safe guard, this won't succeed unless the queue is e
mpty. |
| 221 |
| 222 Additional Information |
| 223 ---------------------- |
| 224 The above tutorial covers the basic operations of creating queues, writing messa
ges, |
| 225 reading messages, deleting messages, and deleting queues. There are a |
| 226 few utility methods in boto that might be useful as well. For example, |
| 227 to count the number of messages in a queue: |
| 228 |
| 229 >>> q.count() |
| 230 10 |
| 231 |
| 232 This can be handy but is command as well as the other two utility methods |
| 233 I'll describe in a minute are inefficient and should be used with caution |
| 234 on queues with lots of messages (e.g. many hundreds or more). Similarly, |
| 235 you can clear (delete) all messages in a queue with: |
| 236 |
| 237 >>> q.clear() |
| 238 |
| 239 Be REAL careful with that one! Finally, if you want to dump all of the |
| 240 messages in a queue to a local file: |
| 241 |
| 242 >>> q.dump('messages.txt', sep='\n------------------\n') |
| 243 |
| 244 This will read all of the messages in the queue and write the bodies of |
| 245 each of the messages to the file messages.txt. The option sep argument |
| 246 is a separator that will be printed between each message body in the file. |
OLD | NEW |