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