LoginSignup
40

More than 3 years have passed since last update.

[GoogleCloudStorage] GCSのPythonAPIの使い方 [備忘]

Last updated at Posted at 2020-01-12

1行で

  • GCSのPythonAPI(google-cloud-storage)のよく使う処理をベタ書き&ラッパー関数としてここに作っておく

GCSをPythonで使うたびに公式ページでいろいろ調べに行っているのがあまりに効率悪いのですぐコピペできるようにQiitaに書いておく

認証通す

pip install google-cloud-storageで事前にライブラリ自体はインストールしておく

また、以下の前提で話を進める

  • Python>=3.5
  • google-cloud-storage==1.23.0

GoogleCloudPlatform上で実行

GCP上ならば別にクレデンシャル情報は不要

from google.cloud import storage as gcs

project_id = "{ProjectName}"
client = gcs.Client(project_id)

ローカルで実行

ローカルで実行するにはサービスアカウントのjsonファイルを手元に用意してパスを通しておく必要あり

やり方は公式を参照

from google.cloud import storage as gcs
from google.oauth2 import service_account

key_path = '{クレデンシャルを格納しているPath}'
credential = service_account.Credentials.from_service_account_file(key_path)

project_id = "{ProjectName}"
client = gcs.Client(project_id, credentials=credential)

バケット一覧を表示する

Projectに存在するバケットがどんなものかを確認する

バケットの一覧を表示
project_id = "{ProjectName}"
client = gcs.Client(project_id, credentials=credential)

[print(bucket.name) for bucket in client.list_buckets()]

ちなみにバケットは名称を指定してオブジェクトを取得できる

バケットのオブジェクトを取得する
project_id = "{ProjectName}"
bucket_name = "{BucketName}"

client = gcs.Client(project_id)
bucket = client.get_bucket(bucket_name)

ローカルファイルをUpload

ローカルにあるファイルをGCSの特定のパスにUploadする

ファイルとしてUpload

まずは、普通にファイルをGCSにUploadするパターン

ローカルファイルのパスを指定してGCSに格納
project_id = "{ProjectName}"
bucket_name = "{BucketName}"
gcs_path = "{GCSFilePath}"
local_path = "{LocalFilePath}"

client = gcs.Client(project_id)
bucket = client.get_bucket(bucket_name)
# 格納するGCSのPathを指定(/xxx/yyy.csv)的な
blob_gcs = bucket.blob(gcs_path)
# ローカルのファイルパスを指定
blob_gcs.upload_from_filename(local_path)

pd.DataFrameとしてUpload

たまに面倒くさくなっていきなりDataFrameからCSVにシリアライズしてGCSに格納したくなるので書いておく

DataFrameをいきなりGCSに入れちゃう
import pandas as pd

project_id = "{ProjectName}"
bucket_name = "{BucketName}"
gcs_path = "{GCSFilePath}"

client = gcs.Client(project_id)
bucket = client.get_bucket(bucket_name)

# 格納するGCSパスを指定
blob = bucket.blob(gcs_path)

df = pd.DataFrame([[1,2,3],[5,6,7]],columns=["x","y","z"])
# DataFrameをGCSにUpload(ヘッダーは入れるが、インデックスは落とす)
blob.upload_from_string(df.to_csv(index=flg_index, header=flg_header, sep=","))

GCSのファイルをDownload

次にDownloadするパターン
ファイルとして落としてくる場合とDataFrameとして落としてくる場合をカバーしておく

ファイルとしてDownload

まずはファイルとしてDownloadする場合

GCSにあるファイルをローカルに落としてくる
project_id = "{ProjectName}"
bucket_name = "{BucketName}"
gcs_path = "{GCSFilePath}"
local_path = "{LocalPath}"

client = gcs.Client(project_id)
bucket = client.get_bucket(bucket_name)

# GCSにあるダウンロードしたいファイルを指定
blob = bucket.blob(gcs_path)
# ファイルとしてローカルに落とす
blob.download_to_filename(local_path)

CSVをDataFrameとして受け取る

変則的だが、CSVファイルを直接pd.DataFrameとして受け取るパターンもよく使うから書いておく

GCSにあるファイルをDataFrameとして受け取る
import pandas as pd

from io import BytesIO

project_id = "{ProjectName}"
bucket_name = "{BucketName}"
gcs_path = "{GCSFilePath}"

client = gcs.Client(project_id)
bucket = client.get_bucket(bucket_name)

# GCSにあるダウンロードしたいファイルを指定
blob = bucket.blob(gcs_path)
# DataFrameとして受け取る(ヘッダーありのCSVを想定)
df = pd.read_csv(BytesIO(blob.download_as_string()))
df.head()

バケット内のファイル一覧を取得する

バケットにあるファイルの中身を確認することもそれなりにあるので、これも記載しておく

バケットを指定してファイル一覧を表示
project_id = "{ProjectName}"
bucket_name = "{BucketName}"
client = gcs.Client(project_id)
bucket = client.get_bucket(bucket_name)

[print(file.name) for file in client.list_blobs(bucket_name)]

機能をクラスでまとめておく

ここまで書いた内容をいちいちコピペするのが面倒なのでクラスにしてまとめておく

ラッパークラスを定義
import pandas as pd

from google.cloud import storage as gcs
from io import BytesIO


class GCSWrapper:
    def __init__(self, project_id, bucket_id):
        """GCSのラッパークラス
        Arguments:
            project_id {str} -- GoogleCloudPlatform Project ID
            bucket_id {str} -- GoogleCloudStorage Bucket ID
        """
        self._project_id = project_id
        self._bucket_id = bucket_id
        self._client = gcs.Client(project_id)
        self._bucket = self._client.get_bucket(self._bucket_id)

    def show_bucket_names(self):
        """バケット名の一覧を表示
        """
        [print(bucket.name) for bucket in self._client.list_buckets()]

    def show_file_names(self):
        """バケット内のファイル一覧を表示
        """
        [print(file.name) for file in self._client.list_blobs(self._bucket)]

    def upload_file(self, local_path, gcs_path):
        """GCSにローカルファイルをアップロード

        Arguments:
            local_path {str} -- local file path
            gcs_path {str} -- gcs file path
        """
        blob = self._bucket.blob(gcs_path)
        blob.upload_from_filename(local_path)

    def upload_file_as_dataframe(self, df, gcs_path, flg_index=False, flg_header=True):
        """GCSにpd.DataFrameをCSVとしてアップロード

        Arguments:
            df {pd.DataFrame} -- DataFrame for upload
            gcs_path {str} -- gcs file path

        Keyword Arguments:
            flg_index {bool} -- DataFrame index flg (default: {False})
            flg_header {bool} -- DataFrame header flg (default: {True})
        """
        blob = self._bucket.blob(gcs_path)
        blob.upload_from_string(df.to_csv(
            index=flg_index, header=flg_header, sep=","))

    def download_file(self, local_path, gcs_path):
        """GCSのファイルをファイルとしてダウンロード

        Arguments:
            local_path {str} -- local file path
            gcs_path {str} -- gcs file path
        """
        blob = self._bucket.blob(gcs_path)
        blob.download_to_filename(local_path)

    def download_file_as_dataframe(self, gcs_csv_path):
        """GCSのファイルをpd.DataFrameとしてダウンロード

        Arguments:
            gcs_csv_path {str} -- gcs file path (only csv file)

        Returns:
            [pd.DataFrame] -- csv data as pd.DataFrame
        """
        blob = self._bucket.blob(gcs_csv_path)
        content = blob.download_as_string()
        df = pd.read_csv(BytesIO(content))
        return df

おしまい

参考

【GoogleCloudPlatform】pythonでGCSバケットのデータを読み出す/書き出す

API Reference

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40