Azure Storage Blobs client library for Pythonを使ってBlobをいろいろ操作してみる

以前のブログで、Azure SDK for PythonのBlob Storage Clientを使ってpandasのDataFrameをcsv形式でBlobストレージへのアップロード方法について書いたのだが、Blob Storage Clientには他にもたくさんいろいろなメソッドが用意されていたりするので、今回は個人的に結構使いそうなメソッドについて試してみる。

rnakamine.hatenablog.com

環境

  • python 3.8.2
  • azure-storage-blob 12.8.0

事前準備

ストレージアカウントの資格情報を取得

Azure Potalからストレージアカウントの接続文字列を取得する。 f:id:rnakamine:20210328070514p:plain

取得した接続文字列を環境変数に追加

$ export AZURE_STORAGE_CONNECTION_STRING="<yourconnectionstring>"

パッケージのインストール

$ pip install azure-storage-blob

コンテナの作成

BlobServiceClientクラスのcreate_container()を使ってコンテナを作成

import os

from azure.storage.blob import BlobServiceClient, BlobClient, ContainerClient

connect_str = os.getenv('AZURE_STORAGE_CONNECTION_STRING')


def main():
    container_name = 'testnakamine'
    blob_service_client = BlobServiceClient.from_connection_string(connect_str)
    blob_service_client.create_container(container_name)


if __name__ == '__main__':
    main()

コンテナのリストを表示

BlobServiceClientクラスのlist_containers()メソッドを使ってコンテナのリストを表示できる。

list_containers()メソッドでContainerPropertiesインスタンスを返すイテレータを取得できるので、これをfor文とかで回してリストを表示させることができる。

def main():
    blob_service_client = BlobServiceClient.from_connection_string(connect_str)
    containers = blob_service_client.list_containers()
    for container in containers:
        print(
            f"Name: {container['name']} Last Modified: {container['last_modified']}")

上記の様に、返されたContainerPropertiesインスタンスからはdictを用いて様々な値にアクセスできる。

docs.microsoft.com

blobのアップロード

BlobServiceClientクラスのget_blob_client()メソッドを使ってBlobClinetインスタンスを取得し、update_blob()メソッドを使ってローカルのファイルをアップロードする。

def main():
    container_name = 'testnakamine'
    blob_name = 'sample.txt'

    blob_service_client = BlobServiceClient.from_connection_string(connect_str)
    blob_client = blob_service_client.get_blob_client(
        container_name, blob=blob_name)

    with open(blob_name, 'rb') as data:
        blob_client.upload_blob(data)

blobの存在確認

上記のupload_blob()メソッドだと、すでにBlobが存在する場合はエラーになる。

BlobClientインスタンスからexists()メソッドを使用し、Blobが存在しているか確認することができる。

def main():
    container_name = 'testnakamine'
    blob_name = 'sample.txt'

    blob_service_client = BlobServiceClient.from_connection_string(connect_str)
    blob_client = blob_service_client.get_blob_client(
        container_name, blob=blob_name)

    if blob_client.exists():
        print('Exists')
    else:
        print('Not exists')

コンテナ内のblobのリストを表示

まずBlobServiceClientクラスのget_blob_client()メソッドを使ってBlobClientインスタンスを取得する。

BlobClientインスタンスlist_blobs()メソッドを使用してBlobPropertiesインスタンスを返すイテレータを取得できるので、それをfor文で回してリストを表示させる。

def main():
    container_name = 'testnakamine'
    blob_service_client = BlobServiceClient.from_connection_string(connect_str)
    container_client = blob_service_client.get_container_client(container_name)

    blobs = container_client.list_blobs()
    for blob in blobs:
        print(blob['name'], blob['last_modified'])

ContainerPropertiesと同様にdictを用いて様々な値にアクセスできる。

docs.microsoft.com

blobのダウンロード

BlobClientインスタンスdownload_blob()メソッドを使って、Blobをダウンロードしそれをファイルに書き込む。

def main():
    container_name = 'testnakamine'
    blob_name = 'sample.txt'
    file_name = 'download.txt'

    blob_service_client = BlobServiceClient.from_connection_string(connect_str)
    blob_client = blob_service_client.get_blob_client(
        container_name, blob=blob_name)

    with open(file_name, 'wb') as download_file:
        download_file.write(blob_client.download_blob().readall())

今回はわかりやすいようにダウンロードしたBlobを別名(download.txt)で保存し確認する。

$ cat download.txt
Hello, World!

blobの削除

BlobClientインスタンスdelete_blob()メソッドを使って、Blobを削除する。

def main():
    container_name = 'testnakamine'
    blob_name = 'sample.txt'

    blob_service_client = BlobServiceClient.from_connection_string(connect_str)
    blob_client = blob_service_client.get_blob_client(
        container_name, blob=blob_name)

    blob_client.delete_blob()

サンプルコード

上記で使用したサンプルコード

github.com

今作ってるもの

これらを使って、ターミナルからUNIXコマンドでファイルやディレクトリを扱う様なCLIツールを作っている途中。 使い勝手としてはaws cliのs3と同じ感じしようかと思っている。

github.com

まだ途中だが、ある程度できた段階でブログにも書いていきたい。