编辑:我的最初假设被部分证明是错误的。我在这里添加了一个冗长的答案,邀请其他人进行压力测试和纠正。
我正在寻找一种以单线程方式利用Boto3 S3 API来模仿线程安全键值存储的方法。简而言之,我想使用调用线程而不是新线程来进行上传。
据我所知,.upload_fileobj()Boto3(或.upload_file())中方法的默认行为是将任务启动到新线程并None立即返回。
从文档:
这是一个托管传输,如有必要,它将在多个线程中执行分段上传。
(如果我一开始的理解是错误的,那么对此进行更正也会有所帮助。这在Boto3 1.9.134中)。
>>> import io
>>> import boto3
>>> bucket = boto3.resource('s3').Bucket('my-bucket-name')
>>> buf = io.BytesIO(b"test")
>>> res = bucket.upload_fileobj(buf, 'testobj')
>>> res is None
True
Run Code Online (Sandbox Code Playgroud)
现在,我们说这buf不是一个短的4字节字符串,而是一个巨大的文本blob,它将花费不小的时间来完全上传。
我还使用此函数来检查是否存在具有给定键的对象:
def key_exists_in_bucket(bucket_obj, key: str) -> bool:
try:
bucket_obj.Object(key).load()
except botocore.exceptions.ClientError:
return False
else:
return True
Run Code Online (Sandbox Code Playgroud)
我的意图是如果对象按名称存在,则不要重写该对象。
这里的竞争状况是显而易见的:异步启动一个上传,然后使用快速检查key_exists_in_bucket(),False如果该对象仍在写入,则返回该对象,然后因此不必要地再次写入它。
有没有一种方法可以确保bucket.upload_fileobj()由当前线程而不是在该方法范围内创建的新线程来调用该方法?
我意识到这会减慢速度。在这种情况下,我愿意牺牲速度。