AWS SQSをPythonで試してみる

CloudFormationでSQSのQueueを作成して、Pythonコードでメッセージの送受信をするところまで試してみます。

CloudFormation

template.yaml

AWSTemplateFormatVersion: '2010-09-09'

Resources:
  SampleSQS:
    Type: AWS::SQS::Queue

Outputs:
  SampleSQSArn:
    Value: !GetAtt SampleSQS.Arn

Propertiesなしの全部デフォルト値のQueueをこれで作成できます。

デプロイ

$ aws cloudformation deploy --template-file template.yaml --stack-name samplesqs

Queueの名前は以下のコマンドでわかります。

$ aws cloudformation describe-stacks --stack-name samplesqs | jq ".Stacks[0].Outputs"
[
  {
    "OutputKey": "SampleSQSArn",
    "OutputValue": "arn:aws:sqs:ap-northeast-1:xxxxxxxxxxxx:samplesqs-SampleSQS-XXXXXXXXXXXX"
  }
]

QueueのURLがあとで必要になるのですが、このコマンドでわかります。

$ aws sqs get-queue-url --queue-name samplesqs-SampleSQS-X9UDN0YW5ADO
{
    "QueueUrl": "https://ap-northeast-1.queue.amazonaws.com/xxxxxxxxxxxx/samplesqs-SampleSQS-XXXXXXXXXXXX"
}

Pythonコード

PythonコードでQueueのメッセージ送受信をしてみます。

sample.py

import json
import boto3

profile = "default"

session = boto3.session.Session(profile_name = profile)
sqs_client = session.client("sqs")

queue_url = "https://ap-northeast-1.queue.amazonaws.com/xxxxxxxxxxxx/samplesqs-SampleSQS-XXXXXXXXXXXX"

# 送信
idx = 1
while idx <= 10: # 10個のメッセージを送信
    message = {"msg": "Hello, world!", "foo": idx}
    sqs_client.send_message(
        QueueUrl = queue_url,
        MessageBody = json.dumps(message),
    )
    idx += 1

# 受信
while True:
    res = sqs_client.receive_message(
        QueueUrl = queue_url,
    )

    # 受信したものをなにか処理 (このサンプルでは表示するだけ)
    delete_entries = [] # 処理済みメッセージ一覧
    id = 1
    for msg in res.get("Messages", []):
        message = json.loads(msg["Body"])
        print(message)
        delete_entries.append({"Id": str(id), "ReceiptHandle": msg["ReceiptHandle"]})
        id += 1

    # 処理済みメッセージを削除
    if len(delete_entries) > 0: # 0件でdelete_message_batchを呼び出すとエラーになる
        sqs_client.delete_message_batch(
            QueueUrl = queue_url,
            Entries = delete_entries,
        )
    else:
        break

実行してみます。

$ python sample.py
{'msg': 'Hello, world!', 'foo': 3}
{'msg': 'Hello, world!', 'foo': 6}
{'msg': 'Hello, world!', 'foo': 1}
{'msg': 'Hello, world!', 'foo': 2}
{'msg': 'Hello, world!', 'foo': 4}
{'msg': 'Hello, world!', 'foo': 10}
{'msg': 'Hello, world!', 'foo': 7}
{'msg': 'Hello, world!', 'foo': 5}
{'msg': 'Hello, world!', 'foo': 8}
{'msg': 'Hello, world!', 'foo': 9}

できました。順序は保証されていないので、受信したメッセージの順番はめちゃめちゃです。