GCS上のオブジェクトを一部だけダウンロードする

はじめに

自分用メモ。欲求は以下

  • GCS上にある数GBとかの大きめのデータの中身を確認したい
  • でもローカルに丸ごと引っ張ってくるのは嫌
  • linuxのheadコマンドみたいに一部だけみたい

comand line(gsutil)

catコマンドのオプションを見てみたら2秒で解決した

$ gsutil cat --help
〜〜略〜〜
OPTIONS
  -h          Prints short header for each object. For example:

                gsutil cat -h gs://bucket/meeting_notes/2012_Feb/*.txt

              This would print a header with the object name before the contents
              of each text object that matched the wildcard.

  -r range    Causes gsutil to output just the specified byte range of the
              object. Ranges are can be of these forms:

                start-end (e.g., -r 256-5939)
                start-    (e.g., -r 256-)
                -numbytes (e.g., -r -5)

              where offsets start at 0, start-end means to return bytes start
              through end (inclusive), start- means to return bytes start
              through the end of the object, and -numbytes means to return the
              last numbytes of the object. For example:

                gsutil cat -r 256-939 gs://bucket/object

              returns bytes 256 through 939, while:

                gsutil cat -r -5 gs://bucket/object

              returns the final 5 bytes of the object.

-hでheader(先頭)をよしなにとってきてくれる。  -rでrangeを指定できる。指定はバイトで指定する

Python

from google.cloud import storage

def gcs_head(bucket_name: str, file_path: str, character_code: str) -> None:
    """
    GCS上のcsvの先頭1MBだけをダウンロードして出力する
    
    input
    bucket_name: str
        gcsのbucket
    file_path: str
        オブジェクトへのパス
    character_code: str
        オブジェクトの文字コード
        downloadしたものはバイト型なので標準出力しようと思うとdecodeする必要がある
    """
    gcs_blob = storage.Client().bucket(bucket_name).blob(file_path)
    head: bytes = gcs_blob.download_as_bytes(end=100000)
    print(head.decode(character_code))


gcs_head(bucket_name="proj_hoge", file_path="sample.txt", character_code="shift-jis")

Blobsのドキュメントを見てると、ダウンロード系のメソッドにはstartとendの引数があって、読み込みの開始位置と終端をバイトで指定可能。