今回は Google Cloud を使って、Python でGoogle ドライブのファイルを操作する方法を紹介します。Google ドライブを外部から操作するには、API が必要になります。今回はその中でもサービスアカウントという種類の API を使っていきます。
API の取得方法を見ていきます。
API の取得方法
まずは Google クラウドのトップページにアクセスをし、コンソールをクリックします。
https://cloud.google.com/?hl=ja
すると次のような同意画面が表示されることがあるので、同意して続行を行います。
コンソールにログインすると、まだプロジェクトが存在しない場合には新しいプロジェクトを作成する画面になります。
プロジェクトの選択から新しいプロジェクトをクリックしてプロジェクトを作成していきます。
プロジェクト名は自由に決めて、作成を行います。
プロジェクトが完成したら続いてAPI キーの取得を行います。
プロジェクトのホーム画面から、左側のメニューを開き、API と サービスを選択します。その中から有効な API と サービスをクリックします。
API と サービスの画面になったら、API と サービスを有効にする をクリックします。
すると 次のような API ライブラリに遷移します。
ここで Drive API を検索します
Google Drive API が見つかったら有効にする をクリックします
続いて認証情報を取得していきます。
API と サービスの中にある認証情報をクリックします。
右側の認証情報を作成から、サービスアカウントを選択します。
サービスアカウントの詳細を入力する画面になりますので、任意のサービスアカウントや ID を入れて作成を進めます
作成したサービスアカウントは Google クラウドのコンソールの左側のメニューで、IAMと管理という項目のサービスアカウントをクリックすることで確認できます。
まだキーが存在しないのでキーを取得していきます。
上記の画像のメールと書いてあるメールアドレスが表示されている部分をクリックします。
するとサービスアカウントの詳細ページに移動します。
項目の中にキーという項目があるのでキーを選択し、鍵を追加から新しい鍵を作成をクリックします。
するとキーのタイプが表示されるのでJSONを選択し、作成を行います。
するとファイルがダウンロードされるので、credentials.jsonなど分かりやすい名前に変更しておきます。
Google ドライブの設定
Google ドライブのファイルを外部から操作するためには、先ほど作成したサービスアカウントにドライブへのアクセス権限を付与する必要があります。
まずはドライブで操作したいフォルダを作成し、そのフォルダの共有から、ユーザー入力の部分に、サービスアカウントのメールアドレスを入力します。
こちらは以下の画像で黒塗の部分に表示されているメールアドレスになります。
また、ここで作成した、フォルダの ID を取得する必要があります。
フォルダー ID は、URL のfolder/の後ろに続く文字列になります。この部分もメモしておきます。
PythonでGoogleDriveにファイルをアップロード
まずは先ほど作成したフォルダに、新しくファイルをアップロードするコードを書いてみます。
認証情報まわり。認証情報はcredentials.jsonに保存している前提です。
import json
import os
import io
import pandas as pd
from google.oauth2 import service_account
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload, MediaIoBaseDownload
# Google Drive APIの認証情報を設定する
SCOPES = ['https://www.googleapis.com/auth/drive']
SERVICE_ACCOUNT_FILE = filename # サービスアカウントキーのJSONファイルパス
def authenticate_drive():
creds = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE, scopes=SCOPES)
service = build('drive', 'v3', credentials=creds)
return service
service = authenticate_drive()
def upload_file_to_drive(service, file_path, folder_id):
file_metadata = {
'name': os.path.basename(file_path),
'parents': [folder_id]
}
media = MediaFileUpload(file_path, mimetype='text/csv')
file = service.files().create(
body=file_metadata,
media_body=media,
fields='id'
).execute()
return file.get('id')
upload_file_to_drive(service, '/content/sample_data/mnist_test.csv',folder_id)
これを実行すると 先ほどのフォルダにmnist_test.csv がアップロードされます。
PythonでGoogleDriveのファイルを読み込み
続いて アップロードしたmnist_test.csv を読み込んでみます。
ローカルにファイルをダウンロードします。
def download_file_from_drive(service, folder_id, file_name, local_file_path):
# Google Driveから指定されたフォルダのCSVファイルをダウンロードする
results = service.files().list(q=f"name='{file_name}' and '{folder_id}' in parents",
spaces='drive',
fields='files(id)').execute()
file_id = results.get('files', [])[0].get('id')
request = service.files().get_media(fileId=file_id)
fh = io.FileIO(local_file_path, mode='wb')
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
print(f"Download {int(status.progress() * 100)}%.")
download_file_from_drive(service, folder_id, 'mnist_test.csv', 'mnist_test.csv')
フォルダーが存在するか確認する
特定のフォルダーが存在するか確認をし、存在する場合はそのまま存在しない場合はフォルダを作成したい、といったようなことがあると思います。
そこでまずはフォルダーが存在するかどうか確認をするコードを書いてみます。
def search_folder_in_drive(service, folder_id, folder_name):
# 指定されたフォルダIDの中で指定された名前のフォルダを検索し、存在すればそのIDを返す
response = service.files().list(q=f"'{folder_id}' in parents and name='{folder_name}' and mimeType='application/vnd.google-apps.folder'",
spaces='drive',
fields='files(id)').execute()
files = response.get('files', [])
if files:
return files[0]['id']
else:
return 'フォルダはありません'
search_folder_in_drive(service, folder_id, 'test')
ファイルが存在するか確認する
同じようにファイルが存在するか確認するコードも書けます
def search_file(service, folder_id, file_name):
results = service.files().list(q=f"name='{file_name}' and '{folder_id}' in parents",
spaces='drive',
fields='files(id)').execute()
files = results.get('files', [])
return files
search_file(service, folder_id, 'mnist_test.csv')
新しいフォルダを作成する
フォルダを作成したい場合は次のように、書くことができます。作成後はフォルダー ID を取得しておくとその後の操作が簡単になります。
def create_folder_in_drive(service, folder_name, parent_folder_id=None):
# 指定された名前の新しいフォルダを作成し、作成したフォルダのIDを返す
file_metadata = {
'name': folder_name,
'mimeType': 'application/vnd.google-apps.folder'
}
if parent_folder_id:
file_metadata['parents'] = [parent_folder_id]
folder = service.files().create(body=file_metadata, fields='id').execute()
return folder.get('id')
create_folder_in_drive(service, 'test', parent_folder_id=folder_id)
以上が基本的なGoogle ドライブ上のファイルを操作する方法 になります。
これができると簡単なクラウドストレージとしてGoogle ドライブを活用できます。
今回のコードはこちらのGoogle Colabで確認できます。