我正在实现一个异步 Python 代码,它使用 aiobotocore 将对象放入 S3 中。
代码是这样的 -
class Foo:
def __init__(self):
self._aiobotocore_session = get_session()
def a():
async with self.s3_client as self._aiobotocore_session.create_client('s3'):
await s3_client.put_object(...)
.... some logic ...
async with self.s3_client as self._aiobotocore_session.create_client('s3'):
await s3_client.put_object(...)
def b():
.... some logic ...
async with self.s3_client as self._aiobotocore_session.create_client('s3'):
await s3_client.put_object(...)
在官方文档中,看起来这是正确的方法。 然而,我不明白为什么我要一遍又一遍地调用
self._aiobotocore_session.create_client('s3')
,从源代码来看,这看起来像是一个昂贵的操作......
我有什么遗漏的吗?
如果我是正确的,缓存创建的客户端的最佳方法是什么? 现在看来我需要重新实现 ClientCreatorContext,以便它将保留客户端初始化
是的,如此处所述:
是的,可以做到,https://docs.python.org/3/library/contextlib.html#contextlib.AsyncExitStack也应该使用,我今晚会考虑制作一个aiohttp示例
并且this是他所指的aiohttp示例。
以下是我设法使其可重复使用的唯一方法
import aiohttp
import asyncio
import aioboto3
import contextlib
class Downloader:
def __init__(self, s3_client) -> None:
self.s3_client = s3_client
async def download(self, bucket_name, object_key, destination_path) -> str:
return await self.s3_client.meta.client.download_file(bucket_name, object_key, destination_path)
async def close(self) -> None:
await self.s3_client.close()
async def main() -> None:
context_stack = contextlib.AsyncExitStack()
session = aioboto3.Session()
s3_client = await context_stack.enter_async_context(session.resource('s3'))
d = Downloader(s3_client)
await d.download("bucket", "my/key1", "/tmp/key1")
await d.download("bucket", "my/key2", "/tmp/key2")
await d.close()
if __name__ == "__main__":
asyncio.run(main())