Search code examples
pythonpython-3.xpython-asyncioamazon-sqsbotocore

ERROR: botocore.exceptions.HTTPClientError: An HTTP Client raised an unhandled exception: 'NoneType' object has no attribute 'request'


So I am pretty new to asynchronous programming in python3. I am creating aws sqs client using types_aiobotocore_sqs and aiobotocore libraries. But I am getting the error mentioned in the title.

Following is the code implementation

url.py file: 

@api_view(["GET"])
def root_view(request):
    async def run_async():
        sqs_helper = await Helper.create(QueueName.TEST_QUEUE.value)
        message = await sqs_helper.get_queue_url()
        return message
    response = asyncio.run(run_async())
    return Response(str(response))

sqs_helper file

class Helper:
    def __init__(self, queue_name: str) -> None:
        self.queue_name = queue_name
        self.access_key_id = env("AWS_ACCESS_KEY_ID")
        self.secret_access_key = env("AWS_SECRET_ACCESS_KEY")
        self.region_name = env("REGION_NAME")
        self.sqs = None

    @classmethod
    async def create(cls, queue_name):
        instance = cls(queue_name)
        await instance.setup()
        return instance

    async def setup(self):
        self.sqs_client = await self.create_sqs_client()
        self.sqs = Sqs(self.sqs_client, self.queue_name)

    async def create_sqs_client(self):
        session = get_session()
        async with session.create_client('sqs', region_name=self.region_name, aws_access_key_id=self.access_key_id, aws_secret_access_key=self.secret_access_key) as client:
            client: SQSClient
        print("TYPE" + str(client))
        return client

     async def get_queue_url(self):
        return await self.sqs.get_queue_url()

Sqs client which initiating the queue

class Sqs:
    def __init__(self, client: SQSClient, queue_name: str) -> None:
        self.queue_name = queue_name
        self._queue_url = ""
        self.client = client

    async def get_queue_url(self) -> str:
        if not self._queue_url:
            try:
                response = await self.client.get_queue_url(QueueName=self.queue_name)
                self._queue_url = response["QueueUrl"]
            except ClientError as err:
                if (
                    err.response.get("Error", {}).get("Code")
                    == "AWS.SimpleQueueService.NonExistentQueue"
                ):
                    raise QueueDoesNotExist(
                        f"Queue {self.queue_name} does not exist"
                    ) from err

                raise err

        return self._queue_url

I am getting the particular error at

response = await self.client.get_queue_url(QueueName=self.queue_name) in Sqs class which in the third code snippet.


Solution

  • When you use async with session.create_client(...) as client, the client object is limited to that context and will be None outside of it. You should assign it directly instead to ensure it's accessible outside that context:

    async def create_sqs_client(self):
        session = get_session()
        client = await session.create_client('sqs', region_name=self.region_name, aws_access_key_id=self.access_key_id, aws_secret_access_key=self.secret_access_key)
        print("TYPE" + str(client))
        return client
    

    Make sure to also handle the closing of the client manually since you're not using async with which would do that for you.