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