tigris-python-sdk について
boto3 と `tigris-boto3-ext` を通じて Tigris を利用する Python SDK です。標準の S3 呼び出しを維持しながら、Tigris のスナップショット、バケットのフォーク、オブジェクトのリネーム、一括取得を利用できます。
主な機能
- 01boto3 の S3 呼び出しで Tigris を利用
- 02バケットのスナップショットを作成・参照
- 03ライブデータやスナップショットからバケットをフォーク
- 04オブジェクトをインプレースでリネーム
- 05オブジェクトの一括取得をストリーミング
活用シーン
- 01スナップショットから過去データを参照
- 02本番データを基に分離したテスト用バケットを作成
- 03ML トレーニング用に多数のオブジェクトを取得
- 04S3 オブジェクトに条件付き書き込みを実行
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ tigrisdata/ skills --skill tigris-python-sdkインストール後、Claude Code で/tigris-python-sdkを入力して読み込まれたか確認します。
同梱ファイルresources/django.md
詳細
Tigris Python SDK
boto3 と tigris-boto3-ext 拡張パッケージを使って、Python から Tigris を利用できます。標準的な S3 呼び出しは変更せずに動作します。拡張機能は有効化された boto3 イベントにヘッダーを挿入し、スナップショット、バケットのフォーク、オブジェクトのインプレースリネーム、バッチ取得用の Bundle API といった Tigris 固有の機能を追加します。
django-storages 経由で Django のアップロードを行う場合は、./resources/django.md を参照してください。
クイックスタート
# 1. Install CLI & authenticate
npm install -g @tigrisdata/cli
tigris login
# 2. Create bucket and access key
tigris buckets create my-bucket
tigris access-keys create "my-bucket-key"
# ⚠ Save the Secret Access Key — shown only once
tigris access-keys assign tid_xxx --bucket my-bucket --role Editor
# 3. Install Python deps
pip install boto3 tigris-boto3-ext
# .env
AWS_ENDPOINT_URL_S3=https://t3.storage.dev
AWS_ACCESS_KEY_ID=tid_xxx
AWS_SECRET_ACCESS_KEY=tsec_yyy
AWS_REGION=auto
import boto3
from tigris_boto3_ext import (
TigrisSnapshotEnabled, create_snapshot, get_snapshot_version,
)
s3 = boto3.client("s3") # picks up env vars
# Create a snapshot-enabled bucket (header injection scoped to the block)
with TigrisSnapshotEnabled(s3):
s3.create_bucket(Bucket="my-bucket")
# Take a snapshot
result = create_snapshot(s3, "my-bucket", snapshot_name="daily-backup")
version = get_snapshot_version(result)
詳しい設定手順については、CLI を使ったスタートガイドを参照してください。
CLI を使ったスタートガイド
ステップ 1:CLI をインストールする
npm install -g @tigrisdata/cli
tigris --version
t3 は tigris のエイリアスです。どちらのコマンドでも同じように使えます。
ステップ 2:認証する
tigris login # opens browser for OAuth
tigris whoami # verify
CI/CD の場合:
tigris configure --access-key <key> --access-secret <secret>
ステップ 3:バケットを作成する
tigris buckets create my-bucket
バケットはデフォルトでプライベートかつグローバルです。匿名での読み取りを許可するには --public を、リージョンを固定するには --locations を使用します。
ステップ 4:アクセスキーを作成する
tigris access-keys create "my-bucket-key"
アクセスキー ID(tid_xxx)とシークレットアクセスキー(tsec_yyy)が出力されます。シークレットが表示されるのは一度だけです。
ステップ 5:バケットにキーを割り当てる
tigris access-keys assign tid_xxx --bucket my-bucket --role Editor
| ロール | 権限 | 用途 |
|---|---|---|
Editor | 読み取り+書き込み+削除 | オブジェクトをアップロード/削除するアプリのコード |
ReadOnly | 読み取りのみ | ダウンロード/一覧表示のみを行うアプリ |
ステップ 6:環境を設定する
# .env (add to .gitignore)
AWS_ENDPOINT_URL_S3=https://t3.storage.dev
AWS_ACCESS_KEY_ID=tid_xxx
AWS_SECRET_ACCESS_KEY=tsec_yyy
AWS_REGION=auto
boto3 は AWS_ENDPOINT_URL_S3 をネイティブに読み取ります(boto3 ≥ 1.34)。この環境変数を設定すれば、クライアント側での上書きは不要です。
ステップ 7:Python の依存関係をインストールする
pip install boto3 tigris-boto3-ext
Python 3.9+ および boto3 ≥ 1.26.0 が必要です。
boto3 クライアントの設定
import boto3
# Reads AWS_ENDPOINT_URL_S3, AWS_ACCESS_KEY_ID, etc. from env
s3 = boto3.client("s3")
# Or configure explicitly
s3 = boto3.client(
"s3",
endpoint_url="https://t3.storage.dev",
aws_access_key_id="tid_xxx",
aws_secret_access_key="tsec_yyy",
region_name="auto",
)
tigris-boto3-ext は、どの boto3 S3 クライアントでも動作します。有効化されると、before-sign.s3.* にハンドラーを登録し、Tigris のヘッダーを挿入します。有効化されたスコープ外の呼び出しは、変更されずにそのまま処理されます。
使用パターン
tigris-boto3-ext では、Tigris 固有の動作を適用するための方法を 3 つ用意しています。呼び出し箇所に合った方法を選んでください。
| パターン | 最適な用途 |
|---|---|
| コンテキストマネージャー | スコープが明確な単発の処理 |
| デコレーター | 常に Tigris の機能が必要な関数 |
| ヘルパー関数 | スコープ設定の手順を挟まずに直接呼び出す場合 |
コンテキストマネージャー
from tigris_boto3_ext import (
TigrisSnapshotEnabled, TigrisSnapshot, TigrisFork, TigrisRename,
)
# Enable snapshots on bucket creation
with TigrisSnapshotEnabled(s3):
s3.create_bucket(Bucket="my-bucket")
# List snapshots for a bucket
with TigrisSnapshot(s3, "my-bucket"):
snapshots = s3.list_buckets()
# Read from a specific snapshot version
with TigrisSnapshot(s3, "my-bucket", snapshot_version="12345"):
obj = s3.get_object(Bucket="my-bucket", Key="file.txt")
# Fork a bucket (current state or from a snapshot)
with TigrisFork(s3, "source-bucket", snapshot_version="12345"):
s3.create_bucket(Bucket="forked-bucket")
# Rename in place — keep scope tight
with TigrisRename(s3):
s3.copy_object(
Bucket="my-bucket",
CopySource="my-bucket/old.txt",
Key="new.txt",
)
デコレーター
from tigris_boto3_ext import snapshot_enabled, with_snapshot, forked_from, with_rename
@snapshot_enabled
def make_snapshot_bucket(s3, name):
return s3.create_bucket(Bucket=name)
@with_snapshot("my-bucket", snapshot_version="12345")
def read_old_config(s3):
return s3.get_object(Bucket="my-bucket", Key="config.json")
@forked_from("source-bucket", snapshot_version="12345")
def make_fork(s3, name):
return s3.create_bucket(Bucket=name)
@with_rename
def rename(s3, bucket, old, new):
return s3.copy_object(Bucket=bucket, CopySource=f"{bucket}/{old}", Key=new)
ヘルパー関数
from tigris_boto3_ext import (
create_snapshot_bucket,
create_snapshot,
list_snapshots,
create_fork,
get_object_from_snapshot,
get_snapshot_version,
list_objects_from_snapshot,
head_object_from_snapshot,
has_snapshot_enabled,
get_bucket_info,
rename_object,
)
create_snapshot_bucket(s3, "my-bucket")
result = create_snapshot(s3, "my-bucket", snapshot_name="backup-1")
version = get_snapshot_version(result)
snapshots = list_snapshots(s3, "my-bucket")
create_fork(s3, "fork-bucket", "my-bucket", snapshot_version=version)
obj = get_object_from_snapshot(s3, "my-bucket", "file.txt", version)
objects = list_objects_from_snapshot(s3, "my-bucket", version, Prefix="data/")
metadata = head_object_from_snapshot(s3, "my-bucket", "file.txt", version)
rename_object(s3, "my-bucket", "old.txt", "new.txt")
# Inspect bucket
if has_snapshot_enabled(s3, "my-bucket"):
info = get_bucket_info(s3, "my-bucket")
# info: { snapshot_enabled, fork_source_bucket, fork_source_snapshot }
スナップショット
バケットの特定時点のコピーです。Tigris は差分のみを保存するため、低コストで作成できます。
# 1. Enable snapshots when creating the bucket
create_snapshot_bucket(s3, "production-data")
# 2. Take a named snapshot
result = create_snapshot(s3, "production-data", snapshot_name="daily-2026-05-07")
version = get_snapshot_version(result)
# 3. Read from the snapshot — historical view
with TigrisSnapshot(s3, "production-data", snapshot_version=version):
obj = s3.get_object(Bucket="production-data", Key="config.json")
# 4. List all snapshots
snaps = list_snapshots(s3, "production-data")
for b in snaps.get("Buckets", []):
print(b["Name"])
スナップショットはバケットの作成時に有効化する必要があります。後から有効化することはできません。
バケットのフォーク
フォークとは、ソースバケットのライブ状態またはスナップショットから作成された独立したバケットです。分岐するまではストレージが共有されるため、フォークの作成には実質的にコストがかかりません。
# Fork from current state
with TigrisFork(s3, "source-bucket"):
s3.create_bucket(Bucket="forked-bucket")
# Fork from a snapshot — common for testing against prod data
create_fork(s3, "test-bucket", "production-data", snapshot_version=version)
# Inspect lineage
info = get_bucket_info(s3, "test-bucket")
print(info["fork_source_bucket"], info["fork_source_snapshot"])
一般的な用途:本番データを使ったテスト/ステージング環境、インシデント発生前のスナップショットからのタイムトラベルデバッグ、ML パイプラインでの実験ごとのワークスペース。
オブジェクトのインプレースリネーム
Tigris では、copy_object と X-Tigris-Rename: true ヘッダーを使ってリネームを実行します。変更されるのはキーのみで、データの書き換えはありません。
from tigris_boto3_ext import TigrisRename, rename_object
# Helper form (recommended)
rename_object(s3, "my-bucket", "old-name.txt", "new-name.txt")
# Context manager — every copy_object inside the block becomes a rename
with TigrisRename(s3):
s3.copy_object(
Bucket="my-bucket",
CopySource="my-bucket/old.txt",
Key="new.txt",
)
TigrisRename/with_rename のスコープは狭く保ってください。ブロック内の copy_object はすべてリネームとして処理されるため、無関係なコピーは想定どおりに動作しません。
条件付き書き込み
Tigris は、楽観的並行性制御と未作成時のみ作成するセマンティクスに対応する、標準の S3 前提条件ヘッダー(If-Match、If-None-Match、If-Modified-Since、If-Unmodified-Since)をサポートしています。これらは boto3 の標準パラメーターであり、boto3 がすでにそのまま渡すため、tigris-boto3-ext による追加機能はありません。
from botocore.exceptions import ClientError
# Create-only (fail if the key already exists)
try:
s3.put_object(
Bucket="my-bucket",
Key="config.json",
Body=b'{"version": 1}',
IfNoneMatch="*",
)
except ClientError as e:
if e.response["Error"]["Code"] == "PreconditionFailed":
print("Object already exists")
else:
raise
# Optimistic concurrency — read, modify, write only if unchanged
head = s3.head_object(Bucket="my-bucket", Key="config.json")
etag = head["ETag"]
new_body = b'{"version": 2}'
try:
s3.put_object(
Bucket="my-bucket",
Key="config.json",
Body=new_body,
IfMatch=etag,
)
except ClientError as e:
if e.response["Error"]["Code"] == "PreconditionFailed":
# Someone else wrote the object since we read it — retry the read-modify-write
...
else:
raise
| boto3 パラメーター | 動作 | 一般的な用途 |
|---|---|---|
IfMatch=<etag> | 現在の ETag が一致する場合にのみ書き込みます | 楽観的並行性制御/更新の消失防止 |
IfNoneMatch="*" | オブジェクトが存在しない場合にのみ書き込みます | 一度限りの作成/冪等な書き込み |
IfNoneMatch=<etag> | 現在の ETag が異なる場合にのみ書き込みます | 同一データの再アップロードをスキップ |
IfModifiedSince | 指定した RFC 1123 タイムスタンプ以降に更新されている場合にのみ処理します | 条件付き読み取り/キャッシュ検証 |
IfUnmodifiedSince | 指定した RFC 1123 タイムスタンプ以降に更新されていない場合にのみ処理します | 時間制限付きの楽観的並行性制御 |
前提条件に失敗すると、Error.Code == "PreconditionFailed"(HTTP 412)の ClientError が発生します。この特定のコードを捕捉してください。NoSuchKey やスロットリングなどにも同じ例外型が使われるため、すべての ClientError を握りつぶさないでください。
IfMatch/IfNoneMatch は put_object、copy_object、get_object、head_object、delete_object で使用できます。
Bundle API
多数のオブジェクトを単一のストリーミング tar アーカイブで取得します。オブジェクトごとのラウンドトリップがレイテンシの大部分を占める ML トレーニング向けに設計されています。
import tarfile
from tigris_boto3_ext import bundle_objects, BundleError, BUNDLE_ON_ERROR_FAIL
keys = [f"dataset/train/img_{i:05d}.jpg" for i in range(1000)]
response = bundle_objects(s3, "my-dataset-bucket", keys)
with tarfile.open(fileobj=response, mode="r|") as tar:
for member in tar:
if member.name == "__bundle_errors.json":
continue # error manifest — skip
f = tar.extractfile(member)
if f is not None:
data = f.read()
# feed to training pipeline
エラーモード:
- デフォルト:欠落または取得に失敗したオブジェクトは tar 内の
__bundle_errors.jsonに記録されます。一部の取得に成功すれば問題ありません。 on_error=BUNDLE_ON_ERROR_FAIL:失敗があるとstatus_codeとbodyを含むBundleErrorが発生します。すべてのキーが存在している必要がある推論で使用してください。
try:
response = bundle_objects(s3, "my-bucket", keys, on_error=BUNDLE_ON_ERROR_FAIL)
except BundleError as e:
print(f"Bundle failed (HTTP {e.status_code}): {e.body}")
tar は必ずストリーミングモード(mode="r|")で開いてください。アーカイブ全体をメモリ上に展開しないでください。
一般的なワークフロー
バックアップと復元
import boto3
from tigris_boto3_ext import (
create_snapshot_bucket, create_snapshot, create_fork, get_snapshot_version,
)
s3 = boto3.client("s3")
create_snapshot_bucket(s3, "production-data")
# Daily snapshot
result = create_snapshot(s3, "production-data", snapshot_name="daily-backup")
version = get_snapshot_version(result)
# Restore: fork the snapshot into a recovered bucket
create_fork(s3, "restored-data", "production-data", snapshot_version=version)
本番データを使ったテスト
result = create_snapshot(s3, "production-data", snapshot_name="for-tests")
version = get_snapshot_version(result)
create_fork(s3, "test-data", "production-data", snapshot_version=version)
try:
# Writes to test-data don't touch production
s3.put_object(Bucket="test-data", Key="experiment.txt", Body=b"...")
finally:
s3.delete_bucket(Bucket="test-data")
タイムトラベルクエリ
from tigris_boto3_ext import get_object_from_snapshot, list_objects_from_snapshot
old = get_object_from_snapshot(s3, "my-bucket", "config.json", "12345")
config = old["Body"].read()
old_logs = list_objects_from_snapshot(
s3, "my-bucket", "12345", Prefix="logs/2025/12/",
)
for obj in old_logs.get("Contents", []):
print(obj["Key"])
仕組み
tigris-boto3-ext は、コンテキスト/デコレーターが有効なときに Tigris ヘッダーを挿入するため、boto3 の before-sign.s3.* イベントにハンドラーを登録します。
| ヘッダー | 目的 |
|---|---|
X-Tigris-Enable-Snapshot: true | バケット作成時にスナップショットを有効にします |
X-Tigris-Snapshot: true; name=<name> | 名前付きスナップショットを作成します |
X-Tigris-Snapshot: <bucket> | バケットのスナップショットを一覧表示します |
X-Tigris-Snapshot-Version: <version> | 特定のスナップショットバージョンから読み取ります |
X-Tigris-Fork-Source-Bucket: <bucket> | このバケットを元にフォークします |
X-Tigris-Fork-Source-Bucket-Snapshot: <ver> | 特定のスナップショットを元にフォークします |
X-Tigris-Rename: true | CopyObject をその場での名前変更に切り替えます |
HeadBucket のレスポンスには X-Tigris-Enable-Snapshot、X-Tigris-Fork-Source-Bucket、X-Tigris-Fork-Source-Bucket-Snapshot が含まれ、get_bucket_info() および has_snapshot_enabled() を通じて参照できます。
重要なルール
必ず行うこと:
- バケットの作成時にスナップショットを有効にします。有効化を後から行うことはできません
create_snapshotの直後にget_snapshot_version(result)を取得します。読み取りやフォークに必要です- Bundle API のレスポンスはストリーミングします(
mode="r|")。tar 全体をメモリに読み込まないでください - tar メンバーを反復処理する際は
__bundle_errors.jsonをスキップします TigrisRename/with_renameのスコープは狭く保ちます。その中で実行するすべてのcopy_objectがリネームになります
絶対に行わないこと:
region_nameに実在する AWS リージョンをハードコードしないでください。autoを使用します- フォークの作成に費用がかからない場合は、テストに本番バケットを直接使用しないでください
AWS_ENDPOINT_URL_S3を忘れないでください。設定しないと、boto3 は Tigris ではなく AWS S3 にアクセスします
既知の問題
| 問題 | 原因と対処法 |
|---|---|
| スナップショットの呼び出しが 404/409 で失敗する | バケットでスナップショットが有効になっていません。create_snapshot_bucket を使用して再作成します。 |
copy_object によって無関係なファイルがリネームされる | TigrisRename ブロックの範囲が広すぎます。リネームの呼び出しだけを囲みます。 |
| Bundle の反復処理がハングする | tar が非ストリーミングモードで開かれています。"r" ではなく mode="r|" を使用します。 |
BundleError が予期せず発生する | BUNDLE_ON_ERROR_FAIL が渡されています。デフォルトモードでは tar 内のエラーが報告されます。 |
| 呼び出し先が Tigris ではなく AWS になる | AWS_ENDPOINT_URL_S3 が未設定です。環境変数をエクスポートするか、endpoint_url= を明示的に渡します。 |
| フォークでスナップショットが有効になっていない | フォークにはスナップショット機能が引き継がれません。フォーク側で別途有効にします。 |
CLI クイックリファレンス
t3 は tigris のエイリアスです。
# Auth
tigris login
tigris whoami
# Buckets
tigris buckets create <name> [--public] [--locations <region>]
tigris buckets list
tigris buckets delete <name>
# Access keys
tigris access-keys create "<name>"
tigris access-keys assign <tid_xxx> --bucket <name> --role Editor
# Snapshots & forks (also doable from Python via this skill)
tigris buckets snapshot <bucket> --name <snapshot-name>
tigris buckets snapshots <bucket>
tigris buckets fork <new> --source <bucket> [--snapshot <version>]
関連スキル
- file-storage — Tigris の一般的なセットアップと、JS/TS の
@tigrisdata/storageSDK - tigris-snapshots-forking — CLI 側のスナップショット/フォークのワークフロー
- tigris-agent-kit — エージェントのストレージワークフロー(サンドボックス用フォーク、チェックポイント)
- tigris-sdk-guide — 言語ごとの SDK の選び方