我是 boto3的一个新用户,我正在使用 DynamoDB。
DynamoDB
我查看了 DynamoDB api,但是找不到任何能够告诉我表是否已经存在的方法。
处理这个问题的最佳方法是什么?
我是否应该尝试创建一个新表并使用 try catch 包装它?
可以使用 描述表 API 确定表是否存在。
示例代码:
from __future__ import print_function # Python 2/3 compatibility import os os.environ["TZ"] = "UTC" import boto3 client = boto3.client('dynamodb', region_name='us-west-2', endpoint_url="http://localhost:8000") response = client.describe_table( TableName='Movies' ) print(response)
如果表存在:-
如果表不存在:-
你会得到 ResourceNotFoundException
ResourceNotFoundException
异常: 发生错误(ResourceNotF 调用 DescribeTable 操作时: 不能对 一张不存在的桌子
另一种方式:-
或者,您可以使用文档中的 table.wait_until_exists():
table.wait_until_exists()
等待直到此表存在。此方法调用 Table _ vis. wait () ,它轮询。 每20秒执行一次 DynamoDB.Client.description _ table () ,直到成功执行 状态。在25次检查失败后返回一个错误。 参见: AWS API 文档 请求语法 table.wait_until_exists() 报税表 None
等待直到此表存在。此方法调用 Table _ vis. wait () ,它轮询。 每20秒执行一次 DynamoDB.Client.description _ table () ,直到成功执行 状态。在25次检查失败后返回一个错误。
参见: AWS API 文档
请求语法
报税表
None
通过阅读文档,我可以看到有三种方法可以检查表是否存在。
ResourceInUseException
对我来说,如果您只想创建一个表,第一个选项听起来更好。
编辑: 我发现有些人发现很难捕捉到例外。我将在下面提供一些代码,让您了解如何在 boto3中处理异常。
例子一
import boto3 dynamodb_client = boto3.client('dynamodb') try: response = dynamodb_client.create_table( AttributeDefinitions=[ { 'AttributeName': 'Artist', 'AttributeType': 'S', }, { 'AttributeName': 'SongTitle', 'AttributeType': 'S', }, ], KeySchema=[ { 'AttributeName': 'Artist', 'KeyType': 'HASH', }, { 'AttributeName': 'SongTitle', 'KeyType': 'RANGE', }, ], ProvisionedThroughput={ 'ReadCapacityUnits': 5, 'WriteCapacityUnits': 5, }, TableName='test', ) except dynamodb_client.exceptions.ResourceInUseException: # do something here as you require pass
例子2
import boto3 dynamodb_client = boto3.client('dynamodb') table_name = 'test' existing_tables = dynamodb_client.list_tables()['TableNames'] if table_name not in existing_tables: response = dynamodb_client.create_table( AttributeDefinitions=[ { 'AttributeName': 'Artist', 'AttributeType': 'S', }, { 'AttributeName': 'SongTitle', 'AttributeType': 'S', }, ], KeySchema=[ { 'AttributeName': 'Artist', 'KeyType': 'HASH', }, { 'AttributeName': 'SongTitle', 'KeyType': 'RANGE', }, ], ProvisionedThroughput={ 'ReadCapacityUnits': 5, 'WriteCapacityUnits': 5, }, TableName=table_name, )
例子3
import boto3 dynamodb_client = boto3.client('dynamodb') try: response = dynamodb_client.describe_table(TableName='test') except dynamodb_client.exceptions.ResourceNotFoundException: # do something here as you require pass
import boto3 from botocore.exceptions import ClientError TABLE_NAME = "myTableName" dynamodb = boto3.resource('dynamodb', endpoint_url="https://dynamodb.us-east-1.amazonaws.com") table = dynamodb.Table(TABLE_NAME) try: response = client.describe_table(TableName=TABLE_NAME) except ClientError as ce: if ce.response['Error']['Code'] == 'ResourceNotFoundException': print "Table " + TABLE_NAME + " does not exist. Create the table first and try again." else: print "Unknown exception occurred while querying for the " + TABLE_NAME + " table. Printing full error:" pprint.pprint(ce.response)
您可以使用任何 boto3 Table 实例对象的 . table _ status attr。如果存在,则返回其状态(CREATING、 UPDATING、 DELEING、 Aactive)或抛出异常 botocore.exceptions.ClientError: Requested resource not found: Table: <YOUR_TABLE_NAME> not found。您可以将这些条件包装到 try/but 中,以获得关于当前表状态的完整信息。
botocore.exceptions.ClientError: Requested resource not found: Table: <YOUR_TABLE_NAME> not found
import boto3 from botocore.exceptions import ClientError dynamodb = boto3.resource('dynamodb', region_name='us-west-2') table = dynamodb.Table('your_table_name_str') try: is_table_existing = table.table_status in ("CREATING", "UPDATING", "DELETING", "ACTIVE") except ClientError: is_table_existing = False print "Table %s doesn't exist." % table.name
如果您不想使用 boto3.client而只使用 boto3.resource,可以选择其他方法:
boto3.client
boto3.resource
import boto3 database = boto3.resource('dynamodb', endpoint_url="http://localhost:8000") table_name = 'MyTable' table_names = [table.name for table in database.tables.all()] if table_name in table_names: print('table', table_name, 'exists')
请注意,这取决于您是使用客户端还是使用资源。如果您使用 boto3.client(),您可以使用3个方法的接受答案建议。如果使用 boto3.resource(),则只能使用 dynamodb_resource.create_table()并检查异常。
boto3.client()
boto3.resource()
dynamodb_resource.create_table()
try: table = dynamodb_resource.create_table( ... ) table.meta.client.get_waiter('table_exists').wait(TableName=your_table_name) except ResourceInUseException: # do sth here
我知道,如果在 table.split (0,-1)和 table 之间有超过10个表,那么这样做的风险会很小。但是,它确实保存了抛出异常等等。 遗憾的是,文档 https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_ListTables.html(示例)暗示返回列表中的第一个表将是搜索项,但事实并非如此。.
类 Dynamo {
private m_db!: DynamoDB; private async ensure_table(name: string) { const search = await this.db().listTables({ ExclusiveStartTableName: name.slice(0, -1), Limit: 10 }); const exists = search.TableNames?.includes(name); exists || await this.create_table(name); } private async create_table(name: string) { // create the table here } private db(): DynamoDB { return this.m_db || (this.m_db = this.create_db()); } private create_db = (): DynamoDB => { return new DynamoDB({apiVersion: "2012-08-10"}); } }
}
您可以使用方便的资源 API,同时仍然处理和捕获客户端 API 级别的异常,因为您可以从资源访问客户端!这使得检查 table 是否存在的方法成为我所发现的最优雅的方法:
resource = boto3.resource('dynamodb', region_name='eu-north-1') def table_exists(table_name: str) -> bool: try: resource.Table(table_name).table_status except resource.meta.client.exceptions.ResourceNotFoundException: return False return True print(table_exists('dummy_table'))