boto3にキーが存在するかどうかを知りたい。バケットの内容をループして、一致する場合はキーを確認できます。
しかし、それは長くなり過ぎるようです。Boto3の公式ドキュメントには、これを行う方法が明記されています。
明らかなことを見逃しているかもしれません。誰か私にこれを達成する方法を教えてもらえますか?
boto3にキーが存在するかどうかを知りたい。バケットの内容をループして、一致する場合はキーを確認できます。
しかし、それは長くなり過ぎるようです。Boto3の公式ドキュメントには、これを行う方法が明記されています。
明らかなことを見逃しているかもしれません。誰か私にこれを達成する方法を教えてもらえますか?
回答:
Boto 2のboto.s3.key.Key
オブジェクトには、exists
HEADリクエストを実行して結果を確認することにより、S3にキーが存在するかどうかをチェックするメソッドがありましたが、存在しないようです。あなたはそれを自分でしなければなりません:
import boto3
import botocore
s3 = boto3.resource('s3')
try:
s3.Object('my-bucket', 'dootdoot.jpg').load()
except botocore.exceptions.ClientError as e:
if e.response['Error']['Code'] == "404":
# The object does not exist.
...
else:
# Something else has gone wrong.
raise
else:
# The object does exist.
...
load()
問題のオブジェクトが大きい場合やバケット内に多くのオブジェクトがある場合でも、単一のキーに対するHEADリクエストを実行します。これは高速です。
もちろん、使用する予定があるため、オブジェクトが存在するかどうかを確認している場合もあります。その場合は、を忘れload()
てa get()
またはorをdownload_file()
直接実行し、そこでエラーのケースを処理できます。
boto3
、現時点で実行できる最善の方法は、呼び出しhead_object
てキーのメタデータを取得してフェッチし、存在しない場合は結果のエラーを処理することです。
exists
ブール値がなくなるようにサンプルコードを少し変更しましたが、人々がこれを自分たちの状況に適応させることになっていることは明らかです(私は願っています!)。
e.response['Error']['Code']
ような値が表示されます。これがライブラリのバージョンの違いによるものか、API自体の変更によるものかは、この回答が書かれてから確認していません。どちらの方法でも、私のバージョンのboto3では、チェックよりも短い方法は、最初にのみキャッチすることです。"NoSuchKey"
"404"
e.response['Error']['Code']
s3.meta.client.exceptions.NoSuchKey
client
(とは対照的にresource
)を行うs3.head_object(Bucket='my_bucket', Key='my_key')
のではなくs3.Object(...).load()
制御フローに例外を使用することはあまり好きではありません。これは、boto3で機能する代替アプローチです。
import boto3
s3 = boto3.resource('s3')
bucket = s3.Bucket('my-bucket')
key = 'dootdoot.jpg'
objs = list(bucket.objects.filter(Prefix=key))
if any([w.key == path_s3 for w in objs]):
print("Exists!")
else:
print("Doesn't exist")
私が見つけた最も簡単な方法(そしておそらく最も効率的な方法)は次のとおりです。
import boto3
from botocore.errorfactory import ClientError
s3 = boto3.client('s3')
try:
s3.head_object(Bucket='bucket_name', Key='file_path')
except ClientError:
# Not found
pass
s3 = boto3.client('s3')
if e.response['ResponseMetadata']['HTTPStatusCode'] == 404:
Boto3で、フォルダー(プレフィックス)またはlist_objectsを使用してファイルをチェックする場合。オブジェクトが存在するかどうかのチェックとして、応答ディクショナリーに「コンテンツ」の存在を使用できます。@EvilPuppetMasterが提案するように、これはtry / exceptキャッチを回避する別の方法です
import boto3
client = boto3.client('s3')
results = client.list_objects(Bucket='my-bucket', Prefix='dootdoot.jpg')
return 'Contents' in results
s3:GetObject
だけで権限をs3:ListBucket
権限
だけでなくclient
、bucket
あまりにも:
import boto3
import botocore
bucket = boto3.resource('s3', region_name='eu-west-1').Bucket('my-bucket')
try:
bucket.Object('my-file').get()
except botocore.exceptions.ClientError as ex:
if ex.response['Error']['Code'] == 'NoSuchKey':
print('NoSuchKey')
bucket.Object(key).last_modified
。
あなたは使用することができますS3Fsを基本的に一般的なファイル・システムのスタイルのオペレーションを公開boto3のラッパーであります:
import s3fs
s3 = s3fs.S3FileSystem()
s3.exists('myfile.txt')
import boto3
client = boto3.client('s3')
s3_key = 'Your file without bucket name e.g. abc/bcd.txt'
bucket = 'your bucket name'
content = client.head_object(Bucket=bucket,Key=s3_key)
if content.get('ResponseMetadata',None) is not None:
print "File exists - s3://%s/%s " %(bucket,s3_key)
else:
print "File does not exist - s3://%s/%s " %(bucket,s3_key)
FWIW、ここに私が使用している非常にシンプルな機能があります
import boto3
def get_resource(config: dict={}):
"""Loads the s3 resource.
Expects AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY to be in the environment
or in a config dictionary.
Looks in the environment first."""
s3 = boto3.resource('s3',
aws_access_key_id=os.environ.get(
"AWS_ACCESS_KEY_ID", config.get("AWS_ACCESS_KEY_ID")),
aws_secret_access_key=os.environ.get("AWS_SECRET_ACCESS_KEY", config.get("AWS_SECRET_ACCESS_KEY")))
return s3
def get_bucket(s3, s3_uri: str):
"""Get the bucket from the resource.
A thin wrapper, use with caution.
Example usage:
>> bucket = get_bucket(get_resource(), s3_uri_prod)"""
return s3.Bucket(s3_uri)
def isfile_s3(bucket, key: str) -> bool:
"""Returns T/F whether the file exists."""
objs = list(bucket.objects.filter(Prefix=key))
return len(objs) == 1 and objs[0].key == key
def isdir_s3(bucket, key: str) -> bool:
"""Returns T/F whether the directory exists."""
objs = list(bucket.objects.filter(Prefix=key))
return len(objs) > 1
(静かに上書きするのではなく)キーが存在するかどうかを確認するだけの場合は、最初にこのチェックを実行します。
import boto3
def key_exists(mykey, mybucket):
s3_client = boto3.client('s3')
response = s3_client.list_objects_v2(Bucket=mybucket, Prefix=mykey)
if response:
for obj in response['Contents']:
if mykey == obj['Key']:
return True
return False
if key_exists('someprefix/myfile-abc123', 'my-bucket-name'):
print("key exists")
else:
print("safe to put new bucket object")
# try:
# resp = s3_client.put_object(Body="Your string or file-like object",
# Bucket=mybucket,Key=mykey)
# ...check resp success and ClientError exception for errors...
これを試してください
import boto3
s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket_name') # just Bucket name
file_name = 'A/B/filename.txt' # full file path
obj = list(bucket.objects.filter(Prefix=file_name))
if len(obj) > 0:
print("Exists")
else:
print("Not Exists")
ディレクトリまたはバケットに1000未満の場合、それらのセットを取得し、このセットにそのようなキーがあるかどうかを確認した後、次のようにできます。
files_in_dir = {d['Key'].split('/')[-1] for d in s3_client.list_objects_v2(
Bucket='mybucket',
Prefix='my/dir').get('Contents') or []}
このようなコードmy/dir
は、が存在しなくても機能します。
http://boto3.readthedocs.io/en/latest/reference/services/s3.html#S3.Client.list_objects_v2
S3_REGION="eu-central-1"
bucket="mybucket1"
name="objectname"
import boto3
from botocore.client import Config
client = boto3.client('s3',region_name=S3_REGION,config=Config(signature_version='s3v4'))
list = client.list_objects_v2(Bucket=bucket,Prefix=name)
for obj in list.get('Contents', []):
if obj['Key'] == name: return True
return False
boto3の場合、ObjectSummaryを使用して、オブジェクトが存在するかどうかを確認できます。
Amazon S3バケットに保存されているオブジェクトの概要が含まれています。このオブジェクトには、オブジェクトの完全なメタデータまたはそのコンテンツが含まれていません
import boto3
from botocore.errorfactory import ClientError
def path_exists(path, bucket_name):
"""Check to see if an object exists on S3"""
s3 = boto3.resource('s3')
try:
s3.ObjectSummary(bucket_name=bucket_name, key=path).load()
except ClientError as e:
if e.response['Error']['Code'] == "404":
return False
else:
raise e
return True
path_exists('path/to/file.html')
s3.Client.head_objectを呼び出して、ObjectSummaryリソースの属性を更新します。
これは、を使用しない場合はObjectSummary
、の代わりにを使用できることを示しています。この関数は、それが唯一の概要を取得したオブジェクトを取得しません。Object
get()
load()
ここに私のために働く解決策があります。注意点の1つは、事前にキーの正確な形式を知っているため、1つのファイルのみをリストすることです。
import boto3
# The s3 base class to interact with S3
class S3(object):
def __init__(self):
self.s3_client = boto3.client('s3')
def check_if_object_exists(self, s3_bucket, s3_key):
response = self.s3_client.list_objects(
Bucket = s3_bucket,
Prefix = s3_key
)
if 'ETag' in str(response):
return True
else:
return False
if __name__ == '__main__':
s3 = S3()
if s3.check_if_object_exists(bucket, key):
print "Found S3 object."
else:
print "No object found."
これにはBoto3を使用できます。
import boto3
s3 = boto3.resource('s3')
bucket = s3.Bucket('my-bucket')
objs = list(bucket.objects.filter(Prefix=key))
if(len(objs)>0):
print("key exists!!")
else:
print("key doesn't exist!")
ここでキーは、チェックするパスが存在するかどうかです
%timeit
テストから、これが最も速いオプションのようです
それはget()
方法で本当に簡単です
import botocore
from boto3.session import Session
session = Session(aws_access_key_id='AWS_ACCESS_KEY',
aws_secret_access_key='AWS_SECRET_ACCESS_KEY')
s3 = session.resource('s3')
bucket_s3 = s3.Bucket('bucket_name')
def not_exist(file_key):
try:
file_details = bucket_s3.Object(file_key).get()
# print(file_details) # This line prints the file details
return False
except botocore.exceptions.ClientError as e:
if e.response['Error']['Code'] == "NoSuchKey": # or you can check with e.reponse['HTTPStatusCode'] == '404'
return True
return False # For any other error it's hard to determine whether it exists or not. so based on the requirement feel free to change it to True/ False / raise Exception
print(not_exist('hello_world.txt'))
S3バケットにファイルが存在するかどうかを確認する簡単な方法が1つあります。これには例外を使用する必要はありません
sesssion = boto3.Session(aws_access_key_id, aws_secret_access_key)
s3 = session.client('s3')
object_name = 'filename'
bucket = 'bucketname'
obj_status = s3.list_objects(Bucket = bucket, Prefix = object_name)
if obj_status.get('Contents'):
print("File exists")
else:
print("File does not exists")
object_name
バケットに存在する場合、これは正しくありません。たとえばmy_file.txt.oldversion
、を確認すると、誤検知が返されmy_file.txt
ます。ほとんどの場合、アプリケーション全体で使用する可能性のある「ファイルが存在するか」などの広範囲にわたるケースでは、考慮に値する可能性が高いです。
ディレクトリと同等のキーを探す場合は、このアプローチが必要になる場合があります
session = boto3.session.Session()
resource = session.resource("s3")
bucket = resource.Bucket('mybucket')
key = 'dir-like-or-file-like-key'
objects = [o for o in bucket.objects.filter(Prefix=key).limit(1)]
has_key = len(objects) > 0
これは、親キーまたはファイルと同等のキーまたは存在しないキーに対して機能します。私は上記の好ましいアプローチを試して、親キーで失敗しました。
botocore.exceptions.ClientError
ボトコアをインストールする必要があることを使用して例外をキャッチするためだけに気づきました。botocoreは36Mのディスク容量を使用します。これは、awsラムダ関数を使用する場合に特に影響を与えます。その代わりに、例外を使用するだけであれば、追加のライブラリの使用をスキップできます!
コードは次のようになります。あなたの考えを共有してください:
import boto3
import traceback
def download4mS3(s3bucket, s3Path, localPath):
s3 = boto3.resource('s3')
print('Looking for the csv data file ending with .csv in bucket: ' + s3bucket + ' path: ' + s3Path)
if s3Path.endswith('.csv') and s3Path != '':
try:
s3.Bucket(s3bucket).download_file(s3Path, localPath)
except Exception as e:
print(e)
print(traceback.format_exc())
if e.response['Error']['Code'] == "404":
print("Downloading the file from: [", s3Path, "] failed")
exit(12)
else:
raise
print("Downloading the file from: [", s3Path, "] succeeded")
else:
print("csv file not found in in : [", s3Path, "]")
exit(12)
https://www.peterbe.com/plog/fastest-way-to-find-out-if-a-file-exists-in-s3から、これが最速の方法であることが指摘されています。
import boto3
boto3_session = boto3.session.Session()
s3_session_client = boto3_session.client("s3")
response = s3_session_client.list_objects_v2(
Bucket=bc_df_caches_bucket, Prefix=s3_key
)
for obj in response.get("Contents", []):
if obj["Key"] == s3_key:
return True
return False
チェックアウト
bucket.get_key(
key_name,
headers=None,
version_id=None,
response_headers=None,
validate=True
)
特定のキーがバケット内に存在するかどうかを確認します。このメソッドは、HEADリクエストを使用してキーの存在を確認します。戻り値:KeyオブジェクトのインスタンスまたはNone
単にbucket.get_key(keyname)を呼び出して、返されたオブジェクトがNoneかどうかを確認できます。