Python3からCloud Storageを利用(入門)


はじめに

BytesIOとは

BytesIOとは、メモリ上でバイナリデータを扱うための機能であり、Python の標準ライブラリ io に含まれています。バイナリデータとは主に画像や音声などのデータのことを示しています。(C#でいうMemoryStreamのようなものです)

サービスアカウントの作成

Google Cloud Platformにアクセスしてサービスアカウントの作成(API)を行います。
ナビゲーションメニュー > APIとサービス > 認証情報 をクリックし画面に移動します。
そしてサービスアカウントを管理をクリックします。

次の画面ではサービスアカウントを作成をクリックします。

サービスアカウントの詳細を各項目入力していきます。

設定項目 設定内容
サービス アカウント名 (任意の名前に設定)
サービスアカウント説明 (各プロジェクトわかりやすいように任意で設定)

入力が終了したら作成をクリックします。

次の項目ではCloud Storageに関するロールを作ります。今回はテストなのでストレージ管理者(フル権限)を選択しました。
使用アプリケーションに応じてロールを変更するようにしましょう。

最後の項目は省略して大丈夫です。
作成したサービスアカウントをクリックし、キーの項目で鍵を追加をクリックし新しい鍵を作成を選択します。

キーのタイプはJSONを選択して「作成」します。ローカルストレージ内にJSONファイルがダウンロードされるので次の項目でそのJSONファイルを使用し、PythonからCloud Storageを操作していきます。

PythonからCloudStorageを操作

Pythonライブラリーのインストール

今回のプロジェクトで必要なライブラリーを順番にインストールしていきます。
まずCloud Storageにアクセスするために、pip install で Google Cloud Storage のライブラリーをインストールを行います。

pip install google-cloud-storage

BytesIOを経由して Pillowを使いローカル上にファイルに保存するためPillowもインストールしていきます。

pip install requests pillow

Excelファイルなども試したい方向け、openpyxlのインストール

pip install openpyxl

Cloud Storage上のバケットの準備

GUIからGoogle Cloud Storageにアクセスし、バケットを作成し適当な画像ファイルを準備します。
コンソール画面から ナビゲーションメニュー > Cloud Storage で移動します。
今回はPythonのロゴファイルをダウンロードし、image.pngという名前をつけ保存しました。
Pythonのロゴファイル

PythonからCloud Storageにアクセスし画像を取得

最初の方で作成したアクセスユーザのキーを使いCloud Storageにアクセスをしていきます。
まず最初にアクセスユーザのキーを読み込ませる必要があります。2通りのアクセスの参照の仕方を記載します。

# 環境変数を使用しアクセスする場合
import os
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = '{jsonファイルが置かれているパスを記入}'
client= storage.Client()

# 直にjsonファイルへアクセスする場合。
client = storage.Client.from_service_account_json('{jsonファイルが置かれているパスを記入}')

Google Cloud Storage(GCS)に保存した画像ファイルを取得し、ローカル上にファイルを保存するPythonのコードになります。
プログラムがやっている説明として、ファイルを保存したいbucketと保存ファイル名のblobインスタンスを取得します。
画像のバイナリデータが入っているのでBytesIOを経由してPillowで読み込み、任意の画像ファイルをして書き込む流れになります。
blob.download_to_filename を使うことによってファイルをGCSから直接ダウンロードしたりすることもできますが、今回はGCSから落としたファイルに対して編集などを加えたりする想定でPILライブラリーなどにデータを渡す形にしています。

from google.cloud import storage
from PIL import Image
import io

#google cloud storageのクライアントインスタンスを作成
#client = storage.Client()
client = storage.Client.from_service_account_json('●●●●●●●●●●.json')
#バケットのインスタンスを取得
bucket = client.bucket('{任意の名前で作成したバケット名}')

#ファイルのblobインスタンスを取得
blob = bucket.blob('image.png')
img = Image.open(io.BytesIO(blob.download_as_string()))
img.save('sample.png')

PythonからCloud Storageにアクセスしエクセルファイルを取得

GCS上のエクセルファイルを取得しそのBlobデータをBytesIOを経由してopenpyxlで読み込み保存します。
blob.download_to_filename を使うことによってファイルをGCSから直接ダウンロードしたりすることもできますが、今回はGCSから落としたファイルに対して編集などを加えたりする想定でPILライブラリーなどにデータを渡す形にしています。

from google.cloud import storage
import openpyxl
import io

#google cloud storageのクライアントインスタンスを作成
client = storage.Client.from_service_account_json('●●●●●●●●●●.json')
#バケットのインスタンスを取得
bucket = client.bucket('{任意の名前で作成したバケット名}')

##ファイルのblobインスタンスを取得
blob = bucket.blob('test.xlsx')
buffer = io.BytesIO()
blob.download_to_file(buffer)
wb = openpyxl.load_workbook(buffer)
wb.save('./retest.xlsx')

参考にさせていただいた記事

Cloud Storageの画像をリサイズして再アップロードする - Qiita
【Python】 バイナリデータの画像を扱う | かずさプログラマーの雑記帳
Python で Google Cloud Storage と、BigQuery を使う過程でのエラー | Monotalk
Python - GCP Cloud Functions(Python)でCloud Storage上のExcelファイルを編集したい|teratail
PythonでOpenPyXLを使ってExcelファイルの新規作成・保存を行う方法
BytesIO(およびStringIO、cStringIO)の使い方【初心者向け】 | TechAcademyマガジン
Pythonでオンメモリストリームを利用して、中間データを保存せずファイルを扱う | hgrs's Blog
pythonでGoogle Cloud Storageへアクセスしてファイルをアップロード/ダウンロードする方法|ドドテクノ
【Python】 バイナリデータの画像を扱う | かずさプログラマーの雑記帳