Asynchronous MinIO Client SDK
miniopy-async provides an asynchronous interface to the MinIO object storage server, building upon the official synchronous `minio` Python client by integrating `aiohttp`. It aims to stay up-to-date with `minio-py`'s features while providing `asyncio` compatibility. The current version is 1.23.5, and it maintains a frequent release cadence, often aligning with updates to the underlying `minio-py` library or addressing async-specific bugs.
Common errors
-
TypeError: object asyncio.coroutine can't be used in 'await' expression
cause Attempting to call an asynchronous `miniopy-async` method without the `await` keyword, or calling an async function in a synchronous context.fixEnsure all calls to `miniopy-async` methods are prefixed with `await` (e.g., `await client.list_buckets()`). Also, ensure your main execution flow uses `asyncio.run(your_async_main_function())`. -
ConnectionRefusedError: [Errno 111] Connection refused
cause The MinIO server is either not running, not accessible from your environment, or the `endpoint` specified in `Minio` client initialization is incorrect (e.g., wrong host or port).fixVerify that your MinIO server is running and accessible. Double-check the `endpoint` (e.g., `localhost:9000`) used when creating the `Minio` client instance. -
miniopy_async.S3Error: [{'Code': 'NoSuchBucket', 'Message': 'The specified bucket does not exist'}]cause An operation was attempted on a MinIO bucket that does not exist, or the bucket name provided has a typo.fixCheck the bucket name for accuracy. If you intend to create the bucket, ensure your credentials have the necessary permissions and call `client.make_bucket()` first.
Warnings
- breaking Python 3.8 and 3.9 are deprecated and no longer officially supported due to type hinting requirements.
- gotcha All `miniopy-async` methods are coroutines and *must* be `await`ed. Forgetting `await` will result in a `TypeError` or unexpected behavior.
- breaking The `Minio` constructor gained a `server_url` parameter, intended to replace `change_host` for specifying the server endpoint for presigned URLs.
- gotcha The `content-length-range` format for policy conditions in presigned URLs changed from integers to strings.
Install
-
pip install miniopy-async
Imports
- Minio
from minio import Minio
from miniopy_async import Minio
- S3Error
from minio.error import S3Error
from miniopy_async import S3Error
Quickstart
import os
import asyncio
from miniopy_async import Minio, S3Error
async def main():
endpoint = os.environ.get("MINIO_ENDPOINT", "localhost:9000")
access_key = os.environ.get("MINIO_ACCESS_KEY", "minioadmin")
secret_key = os.environ.get("MINIO_SECRET_KEY", "minioadmin")
secure = os.environ.get("MINIO_SECURE", "false").lower() == "true"
client = Minio(
endpoint=endpoint,
access_key=access_key,
secret_key=secret_key,
secure=secure
)
try:
# Example: List all buckets
buckets = await client.list_buckets()
print(f"Successfully connected to MinIO. Found {len(buckets)} buckets:")
for bucket in buckets:
print(f" - {bucket.name} (created at {bucket.creation_date})")
# Example: Make a bucket if it doesn't exist
test_bucket = "my-test-bucket"
found = await client.bucket_exists(test_bucket)
if not found:
await client.make_bucket(test_bucket)
print(f"Bucket '{test_bucket}' created successfully.")
else:
print(f"Bucket '{test_bucket}' already exists.")
except S3Error as e:
print(f"MinIO S3 Error: {e.code} - {e.message}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
if __name__ == "__main__":
# Ensure MinIO_ENDPOINT, MINIO_ACCESS_KEY, MINIO_SECRET_KEY are set
# or MinIO is running locally with default credentials (minioadmin:minioadmin)
asyncio.run(main())