[PYTHON] Definieren Sie die Antwort der boto3-Client-API in der Datenklasse

Einführung

Ich habe mit boto3 gespielt, um zu lernen. Ich dachte, es wäre besser, die mit boto3 erhaltenen Ressourceninformationen in einer Datenklasse zu speichern und darauf zu verweisen (der Grund wird später beschrieben), also schreibe ich sie als Ergebnis.

Was ist boto3 !?

Kurz gesagt, es ist ein SDK für die Arbeit mit AWS-Ressourcen in Python. Es ist in Low-Level-API (Client) und High-Level-API (Resorce) unterteilt. Es gibt endlose andere verwandte Artikel. Wenn Sie also mehr wissen möchten, lesen Sie sie bitte durch.

Dieses Mal werden wir die Low-Level-API verwenden.

Was ist eine Datenklasse?

Es bietet einen Dekorator, der dynamisch spezielle Methoden zuweist, die Klassen wie \ _ \ _ init \ _ \ _ () zugeordnet sind.

Eine Klasse mit dem folgenden Konstruktor

class Wanchan_Nekochan():
    def __init__(self, cat:str, dog:str):
     self.cat =cat
      self.dog = dog

Ohne einen solchen Konstruktor können Sie intelligent schreiben.

@dataclass
class Wanchan_Nekochan():
    cat: str
    dog: str

https://docs.python.org/ja/3/library/dataclasses.html

Im Vergleich zu benannten Tupeln mit ähnlichen Funktionen gibt es die folgenden Unterschiede. -Namedtuple wird nach der Instanziierung unveränderlich (nicht bearbeitbar). Die Datenklasse ist standardmäßig veränderbar (bearbeitbar), aber wenn Sie das eingefrorene Argument als wahr übergeben Unveränderlich werden. ・ Datenklasse liest Daten etwas schneller (Überprüfung erforderlich)

Übung

Verwenden Sie dieses Mal die Methode list_buckets () der Klasse S3.Client, um die Bucket-Liste von S3 abzurufen. (Referenz) Offizielle Referenz https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.list_buckets

Die Definition der Antwort ist der folgende Wörterbuchtyp.

{
    'Buckets': [
        {
            'Name': 'string',
            'CreationDate': datetime
        },
    ],
    'Owner': {
        'DisplayName': 'string',
        'ID': 'string'
    },
    "ResponseMetadata": {
        "RequestId": str,
        "HTTPStatusCode": int,
        "HTTPHeaders": dict,
        "RetryAttempts": int
    }
}

Wenn Sie Informationen aus der zurückgegebenen Antwort erhalten, wird der Schlüssel wie unten gezeigt als Zeichenfolge angegeben.

s3_client = session.client('s3')
data=s3_client.list_buckets()

status_code = data["ResponseMetadata"]["HTTPStatusCode"]
display_name = data["Owner"]["DisplayName"]

Da der Schlüssel durch eine Zeichenfolge angegeben wird, besteht die Gefahr von Rechtschreibfehlern, da die Funktion zur Vervollständigung der Eingabe durch die IDE nicht verwendet werden kann und es problematische Probleme gibt, z. B. nicht zu wissen, bis Sie sich auf den Typ der Daten beziehen.

Wenn Sie die Antwortdefinition im Voraus als Datenklasse definieren, ist ein Punktzugriff möglich, sodass die Eingabe abgeschlossen werden kann und Tipphinweise von mypy rigoros verwendet werden können.

Es gibt keinen Grund, keine Datenklasse zu verwenden !!!

Damit ...

Quelle vorerst

from dataclasses import dataclass
from typing import List
from datetime import datetime

import boto3
from dacite import from_dict


session = boto3.session.Session(profile_name='s3_test')
#BasesClient befindet sich im globalen Bereich, um zu vermeiden, dass APIs mehrmals ausgelöst werden
#In Singleton implementieren
s3_client = session.client('s3')

@dataclass
class Boto3_Response():
    RequestId: str
    HostId: str
    HTTPStatusCode: int
    HTTPHeaders: Dict
    RetryAttempts: int

@dataclass
class Inner_Owner():
    DisplayName: str
    ID: str

@dataclass
class Inner_Buckets():
    Name: str
    CreationDate: datetime

@dataclass
class S3_LIST():
    ResponseMetadata: Boto3_Response
    Owner: Inner_Owner
    Buckets: List[Inner_Buckets]

    @classmethod
    def make_s3_name_list(cls):
        return from_dict(data_class=cls, data=s3_client.list_buckets())


s3_list_response = S3_LIST.make_s3_name_list()

#Statuscode
print(s3_list_response.ResponseMetadata.HTTPStatusCode) #200
#Besitzername
print(s3_list_response.Owner.DisplayName) # nikujaga-kun
# ID
print(s3_list_response.Owner.ID) 
#Eimerliste
print(*[bucket.Name for bucket in s3_list_response.Buckets])

Erklärung unten

from dacite import from_dict

Hier importieren wir eine Drittanbieter-Bibliothek namens Dacite. Dacite (ich habe es als "de" gelesen) ist einfach eine Bibliothek, mit der Wörterbuchtypen an verschachtelte Datenklassen übergeben und instanziiert werden können. https://pypi.org/project/dacite/

@dataclass
class Boto3_Response():
    RequestId: str
    HostId: str
    HTTPStatusCode: int
    HTTPHeaders: Dict
    RetryAttempts: int

@dataclass
class Inner_Owner():
    DisplayName: str
    ID: str

@dataclass
class Inner_Buckets():
    Name: str
    CreationDate: datetime

@dataclass
class S3_LIST():
    ResponseMetadata: Boto3_Response
    Owner: Inner_Owner
    Buckets: List[Inner_Buckets]

    @classmethod
    def make_s3_name_list(cls):
        return from_dict(data_class=cls, data=s3_client.list_buckets())

In der obigen Definition von S3_LIST sind verschiedene Datenklassen Boto3_Response, Inner_Owner, Inner_Buckets als Attributtypen definiert. Wenn Sie die Antwort von list_buckets an S3_LIST übergeben, ohne from_dict of dacite zu verwenden

@classmethod
   def make_s3_name_list(cls):
      return cls(**s3_client.list_buckets())

Es sieht so aus, aber da es als Wörterbuchtyp anstelle einer Klasseninstanz übergeben wird, wird es wütend, wenn es kein solches Attribut gibt.

s3_list_response = S3_LIST.make_s3_name_list()

#Ärgern Sie sich hier über Attributfehler
print(s3_list_response.ResponseMetadata.HTTPStatusCode)

# 'dict' object has no attribute 'HTTPStatusCode'

Wenn Sie versuchen, hier etwas Gutes zu tun, indem Sie es einfach einbetten, wird es schwierig, wie es ist. Ich benutze Dacite als Bibliothek, die gute Arbeit leistet. Sie sollten unendlich auf der Schulter des Riesen reiten.

Schließlich

Datenklasse ist gut

Recommended Posts

Definieren Sie die Antwort der boto3-Client-API in der Datenklasse
Holen Sie sich Google Fit API-Daten in Python
Holen Sie sich Youtube-Daten in Python mithilfe der Youtube-Daten-API
SELECT-Daten mithilfe der Client-Bibliothek mit BigQuery
Fügen Sie AWS-Daten mit boto + gspread in Google Spreadsheet ein
[Road to Intermediate Python] Definieren Sie die Funktion __getattr__ in der Klasse