CLI tool
minio/minio-py avatar
minio/minio-py

minio-py: an S3 client for Python that also speaks RDMA

MinIO Client SDK for Python

1,076 stars371 forksPythonApache-2.0

At a glance

What is it?
The minio-py SDK gives Python applications high level access to any S3 compatible object storage, and it can optionally dispatch uploads and downloads onto MinIO's RDMA path through a native extension. The RDMA mode is opt-in, and the SDK stays pure Python unless you use it.
Who is it for?
Adopt minio-py if your Python application talks to MinIO or another S3 compatible store and you want a synchronous, high level client rather than a raw HTTP wrapper. Do not adopt it for ML training pipelines where data load throughput dominates, unless you are prepared to set up the RDMA prerequisites.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 25 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The client, and what it talks to

The MinIO Python Client SDK provides high level APIs to access any MinIO Object Storage or other Amazon S3 compatible service, and the README is explicit that it covers installing the SDK, connecting to the object storage service, and creating a sample file uploader.

The client is created with the Minio() method and three required parameters. The endpoint is the URL of the target service, the access_key is the access key, or user ID, of a user account in the service, and the secret_key is the secret key, or password, for that user account.

py
from minio import Minio

client = Minio(
    endpoint="play.min.io",
    access_key="Q3AM3UQ867SPQQA43P2F",
    secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
)

Those credentials belong to the MinIO play server, which the README describes as a public MinIO cluster at play.min.io that runs the latest stable version and may be used for testing and development. The warning is worth repeating because it is the kind of thing people copy into a real project by accident: the access credentials in the example are open to the public, and all data uploaded to play should be considered public and world-readable.

The SDK requires Python 3.10 or newer, and it is distributed under the Apache License 2.0 with a NOTICE file. The package name on PyPI is minio, the primary language is Python, and the last push to the repository was on 2026-09-28. The recent releases are 7.2.20 from 2025-11-27, 7.2.19 from 2025-11-24, and 7.2.18 from 2025-09-29, all described as bugfix releases.

The upload example, which is the whole API surface in miniature

The example does four things: it connects to the play server with the example credentials, it creates a bucket named python-test-bucket if it does not already exist, it uploads a file named test-file.txt from /tmp renaming it my-test-file.txt, and it verifies the file was created using mc ls.

The code shows the shape of the API. Bucket existence is a query returning a boolean, and creation is a separate call, so the pattern is an if rather than an upsert:

py
    # Make the bucket if it doesn't exist.
    found = client.bucket_exists(bucket_name=bucket_name)
    if not found:
        client.make_bucket(bucket_name=bucket_name)
        print("Created bucket", bucket_name)
    else:
        print("Bucket", bucket_name, "already exists")

    # Upload the file, renaming it in the process
    client.fput_object(
        bucket_name=bucket_name,
        object_name=destination_file,
        file_path=source_file,
    )

The fput_object call is the file variant, taking a local file path and an object name, which is where the renaming happens: the local name and the object name are different. The f prefix distinguishes it from the data variant.

Error handling uses S3Error, imported from minio.error, caught around main so that a service-side failure prints rather than raising a traceback. That import is also a hint about the design, since S3Error is the S3 protocol's error type rather than a transport exception, and it means the SDK surfaces a single exception type for service errors.

The verification step is the part that makes the example complete, and it uses the MinIO mc command line tool rather than the SDK:

sh
mc ls play/python-test-bucket
[2023-11-03 22:18:54 UTC]  20KiB STANDARD my-test-file.txt

The README also lists the MinIO mc command line tool and the play test server as things the example uses, alongside Python 3.10 or newer.

The RDMA path, which is opt-in and does not change the API

The most interesting part of the SDK is the optional RDMA support, and the design constraint is that the SDK stays pure Python unless it is used.

put_object and get_object can dispatch to MinIO's RDMA path via minio-cpp, and it is strictly opt-in. The example shows the whole mechanism: a client created with enable_rdma=True, marked as opt-in in the comment.

python
client = Minio(
    endpoint="server:9000",
    access_key="...",
    secret_key="...",
    secure=False,
    enable_rdma=True,             # opt-in
)

The dispatch is selected by the shape of the call rather than by a separate method. A put_object with a buffer and a length is a buffer protocol object and selects RDMA, and a get_object with an into= destination buffer and a length selects RDMA and returns bytes.

python
buf = bytearray(1 << 20)
client.put_object(
    bucket_name="b", object_name="o",
    data=buf, length=len(buf),    # buffer-protocol object selects RDMA
)

The prerequisites are specific. It requires libminiocpp.so, built with -DMINIO_CPP_ENABLE_RDMA=ON, on the host's library search path, or pointed at via the MINIOCPP_LIB env var. The RDMA transport it carries, libs3rdma, supports RoCE and native InfiniBand and needs no NVIDIA client library on the host.

The GPU detail is the part that makes this useful for machine learning workloads. GPU buffer pointers, for example CuPy's arr.data.ptr or PyTorch's t.data_ptr(), work as data= and into= arguments unchanged, passed as an int. The SDK links no CUDA itself, and allocating device memory stays the application's job. So a training loop can hand a device pointer straight to the upload path without a host copy.

For multi-NIC hosts there is one more control. Setting S3RDMA_DEVICE pins a particular HCA, and otherwise the first usable device is selected. Two example files ship with it, examples/put_object_rdma.py and examples/get_object_rdma.py.

The examples directory, and what it reveals about the API

The examples directory is long enough that its file names are effectively an index of the SDK, and it is worth scanning because it shows the shape of the whole surface.

The object operations are there in both forms, append_object.py, compose_object.py, and copy_object.py for the multipart and copy paths. The bucket configuration is covered by delete_bucket_cors.py, delete_bucket_encryption.py, delete_bucket_lifecycle.py, delete_bucket_notification.py, delete_bucket_policy.py, delete_bucket_replication.py, and delete_bucket_tags.py, with the matching get_bucket_* files for reading the current configuration back.

The retention features are the most heavyweight part of the list, with delete_object_lock_config.py, delete_object_tags.py, disable_object_legal_hold.py, and enable_object_legal_hold.py. Object lock and legal hold are the compliance features of S3, and having one example per operation suggests the SDK covers them properly rather than partially.

Bucket versioning has its own file, get_bucket_versioning.py, and bucket_exists.py is there as the simplest possible call.

The pattern across all of these is one file per operation, named for the operation. That is a documentation decision as much as a code one, since it means the README does not have to enumerate the API and the examples are usable as a reference by filename.

The repository also has a Makefile whose default target is the test suite, and the test suite has two parts. The check target runs pylint with several checks disabled, then isort in diff mode, then autopep8 in diff mode, then mypy. The tests target runs pytest for the unit tests and then the functional tests through a run_functional_tests.sh script, which is where the SDK is exercised against a real server rather than a mock.

Against boto3, and against the raw S3 API

The realistic alternative for most Python applications is boto3, the AWS SDK.

The difference in approach is in the interface. minio-py is a higher level client, and the operations are named after what you want rather than after the wire protocol, with the file variants handling the local file handling for you.

That higher level comes with a trade. If you need an S3 feature the SDK has not wrapped, you end up either waiting for it to appear or dropping down to a lower layer. The examples directory shows how wide the coverage is, and the gap between that and the full S3 surface is where a boto3 user would feel the difference.

The second alternative is the raw S3 API with plain HTTP and your own signing, which is almost never worth it and is what the SDK exists to avoid.

The third alternative is to not use Python for that part of the system. The RDMA support is the reason to reconsider that, because put_object and get_object can dispatch onto a native RDMA transport, and the SDK gives you that path without leaving Python.

The comparison that actually decides it is usually about the server. If you run MinIO, this SDK is the natural choice because it speaks to the same project's tooling and has the RDMA path. If you run AWS, the service is mature enough that the SDK choice is less consequential, and the deciding factor becomes which client your team already knows.

Editorial conclusion

Adopt minio-py if your Python application talks to MinIO or another S3 compatible store and you want a synchronous, high level client rather than a raw HTTP wrapper. Do not adopt it for ML training pipelines where data load throughput dominates, unless you are prepared to set up the RDMA prerequisites. Verify first that your object store exposes the endpoints the SDK expects, since a partial S3 implementation will fail on some of the bucket management calls.

Frequently asked questions

How do I install minio-py and create a client?

The SDK requires Python 3.10 or newer. Install it with pip3 install minio, or from source with git clone and python setup.py install. Then create a client with the Minio() method, passing the endpoint, the access_key, and the secret_key of a user account in the service.

How do I enable the RDMA fast path in minio-py?

Set enable_rdma=True on the client, which is strictly opt-in, and pass a buffer with a length to put_object or an into= buffer with a length to get_object. The buffer protocol call selects the RDMA path, and the SDK stays pure Python unless you use it.

What does the RDMA mode require on the host?

It requires libminiocpp.so built with -DMINIO_CPP_ENABLE_RDMA=ON on the host's library search path, or pointed at via the MINIOCPP_LIB env var. The libs3rdma transport it carries supports RoCE and native InfiniBand and needs no NVIDIA client library.

Can I upload a GPU buffer with minio-py?

Yes. GPU buffer pointers, for example CuPy's arr.data.ptr or PyTorch's t.data_ptr(), work as data= and into= arguments unchanged, passed as an int. The SDK links no CUDA itself, so allocating device memory stays the application's job.

What licence is minio-py released under?

The Apache License, Version 2.0, with the LICENSE and NOTICE files in the repository. The client is published on PyPI as minio, and the quickstart points to the Python SDK documentation for the complete list of APIs.

Official sources

  1. License: Apache-2.0
  2. minio/minio-py on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/minio-minio-py.svg)](https://hysenlabs.com/projects/minio-minio-py)

Was this useful?