Simple, fast integration with object storage services like Amazon S3, Google Cloud Storage, Azure Blob Storage, and S3-compliant APIs like Cloudflare R2.
list
, with no need to paginate.dict
/list
objects.get_range
and get_ranges
.boto3.Session
objectsTo install obstore using pip:
pip install obstore
Obstore is on conda-forge and can be installed using conda, mamba, or pixi. To install obstore using conda:
conda install -c conda-forge obstore
Full documentation is available on the website.
Classes to construct a store are exported from the obstore.store
submodule:
S3Store
: Configure a connection to Amazon S3.GCSStore
: Configure a connection to Google Cloud Storage.AzureStore
: Configure a connection to Microsoft Azure Blob Storage.HTTPStore
: Configure a connection to a generic HTTP serverLocalStore
: Local filesystem storage providing the same object store interface.MemoryStore
: A fully in-memory implementation of ObjectStore.import boto3
from obstore.store import S3Store
session = boto3.Session()
store = S3Store.from_session(session, "bucket-name", config={"AWS_REGION": "us-east-1"})
Each store class above has its own configuration, accessible through the config
named parameter. This is covered in the docs, and string literals are in the type hints.
Additional HTTP client configuration is available via the client_options
named parameter.
All methods for interacting with a store are exported as top-level functions (not methods on the store
object):
copy
: Copy an object from one path to another in the same object store.delete
: Delete the object at the specified location.get
: Return the bytes that are stored at the specified location.head
: Return the metadata for the specified locationlist
: List all the objects with the given prefix.put
: Save the provided bytes to the specified locationrename
: Move an object from one path to another in the same object store.There are a few additional APIs useful for specific use cases:
get_range
: Get a specific byte range from a file.get_ranges
: Get multiple byte ranges from a single file.list_with_delimiter
: List objects within a specific directory.sign
: Create a signed URL.All methods have a comparable async method with the same name plus an _async
suffix.
import obstore as obs
store = obs.store.MemoryStore()
obs.put(store, "file.txt", b"hello world!")
response = obs.get(store, "file.txt")
response.meta
# {'path': 'file.txt',
# 'last_modified': datetime.datetime(2024, 10, 21, 16, 19, 45, 102620, tzinfo=datetime.timezone.utc),
# 'size': 12,
# 'e_tag': '0',
# 'version': None}
assert response.bytes() == b"hello world!"
byte_range = obs.get_range(store, "file.txt", offset=0, length=5)
assert byte_range == b"hello"
obs.copy(store, "file.txt", "other.txt")
assert obs.get(store, "other.txt").bytes() == b"hello world!"
All of these methods also have async
counterparts, suffixed with _async
.
import obstore as obs
store = obs.store.MemoryStore()
await obs.put_async(store, "file.txt", b"hello world!")
response = await obs.get_async(store, "file.txt")
response.meta
# {'path': 'file.txt',
# 'last_modified': datetime.datetime(2024, 10, 21, 16, 20, 36, 477418, tzinfo=datetime.timezone.utc),
# 'size': 12,
# 'e_tag': '0',
# 'version': None}
assert await response.bytes_async() == b"hello world!"
byte_range = await obs.get_range_async(store, "file.txt", offset=0, length=5)
assert byte_range == b"hello"
await obs.copy_async(store, "file.txt", "other.txt")
resp = await obs.get_async(store, "other.txt")
assert await resp.bytes_async() == b"hello world!"
Read a detailed comparison to object-store-python
, a previous Python library that also wraps the same Rust object_store
crate.