使用Boto3的transact_write_items时触发__enter__错误求助
问题原因与解决方法:DynamoDB transact_write_items 报
__enter__错误 问题描述
编写Python代码调用Boto3的transact_write_items接口向DynamoDB写入数据,执行时控制台打印HERE: __enter__错误,但DynamoDB表已成功新增条目。测试环境为Windows,通过SAM CLI执行命令:
npx cdk ls; sam local invoke ReportManager-Lambda -t ./cdk.out/GlobalStack.template.json -e .\events\create_report.json
原代码如下:
def create_report_and_update_user(db_client, report_info): # TODO:: This will correctly perform operations, but will return a __enter__ error. Figure out why... report_info = json.loads(json.dumps(report_info), parse_float=Decimal) user_email = report_info["email"] report_id = ( "R-" + str(uuid.uuid4()) if not report_info.get("report_id") else report_info.get("report_id") ) report_data = { "report_id": report_id, "creation_date": str(datetime.now()), "email": user_email, "loan_details": report_info["loan_details"], "purchase_details": report_info["purchase_details"], "property_details": report_info["property_details"], "monthly_budget": report_info["monthly_budget"], } serializer = TypeSerializer() report_data = { key: serializer.serialize(value) for key, value in report_data.items() } try: print("open is assigned to %r" % open) with db_client.transact_write_items( TransactItems=[ { "Put": { "TableName": REPORTS_TABLE_NAME, "Item": report_data, "ConditionExpression": "attribute_not_exists(report_id)", } }, ] ) as response: print("Inside transact_write_items") return response except Exception as e: print("HERE: ", e)
错误原因
Boto3的transact_write_items是普通同步API调用方法,不支持上下文管理器(with语句)。强行使用with时,Python会尝试调用该方法返回对象的__enter__方法,但该方法不存在,因此抛出__enter__错误。
数据能成功写入是因为transact_write_items本身已经执行完成,错误是后续上下文管理器触发的,不影响之前的写入操作。你排查的open函数未被覆盖和此错误无关。
解决方法
去掉with语句,直接调用方法并获取响应即可,修改后的代码如下:
def create_report_and_update_user(db_client, report_info): # TODO:: This will correctly perform operations, but will return a __enter__ error. Figure out why... report_info = json.loads(json.dumps(report_info), parse_float=Decimal) user_email = report_info["email"] report_id = ( "R-" + str(uuid.uuid4()) if not report_info.get("report_id") else report_info.get("report_id") ) report_data = { "report_id": report_id, "creation_date": str(datetime.now()), "email": user_email, "loan_details": report_info["loan_details"], "purchase_details": report_info["purchase_details"], "property_details": report_info["property_details"], "monthly_budget": report_info["monthly_budget"], } serializer = TypeSerializer() report_data = { key: serializer.serialize(value) for key, value in report_data.items() } try: print("open is assigned to %r" % open) # 移除with语句,直接调用API response = db_client.transact_write_items( TransactItems=[ { "Put": { "TableName": REPORTS_TABLE_NAME, "Item": report_data, "ConditionExpression": "attribute_not_exists(report_id)", } }, ] ) print("Inside transact_write_items") return response except Exception as e: print("HERE: ", e)
补充说明
Boto3中仅部分涉及资源管理的操作(如特定流操作、客户端专属上下文方法)支持with语句,绝大多数普通API调用都是直接执行并返回结果,无需使用上下文管理器。
内容的提问来源于stack exchange,提问作者Qwerty Qwerts
相关产品推荐
相关产品推荐

