# qiniu: the Python SDK for Qiniu object storage

> The qiniu package is the Python client for Qiniu Resource Storage, a service where objects live in buckets and are reached through upload tokens rather than a shared secret. The SDK is MIT licensed on PyPI, runs on Python 2.7 and 3.x, and the repository carries a wide set of runnable examples for batch, CDN and lifecycle operations.

**qiniu/python-sdk** — Qiniu Resource (Cloud) Storage SDK for Python

- Repository: https://github.com/qiniu/python-sdk
- Stars: 551 · Forks: 264
- Language: Python
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/qiniu-python-sdk

## The SDK is small, and the API shape is the interesting part

The qiniu package is the Python client for Qiniu Resource Storage, and it installs like any other PyPI package.

```bash
$ pip install qiniu
```

The README is written in Chinese, which is consistent with a Chinese cloud provider's developer tooling. The whole upload flow fits in a dozen lines, and it is worth reading closely because it shows the security model of the service rather than just the library.

```python
import qiniu

...
    q = qiniu.Auth(access_key, secret_key)
    key = 'hello'
    data = 'hello qiniu!'
    token = q.upload_token(bucket_name)
    ret, info = qiniu.put_data(token, key, data)
    if ret is not None:
        print('All is OK')
    else:
        print(info) # error message in info
...
```

The structure is a three step design. The Auth object is constructed with an access key and a secret key, the upload_token method mints a token bound to a bucket name, and put_data takes that token, a key and the payload. The token is what travels with the upload, not the secret key, which is the point of the design, since a token can be handed to an untrusted client for a bounded upload without handing over the account credential. The return convention is a tuple, and the README calls it out in the FAQ: the second parameter info keeps the request and response information, on failure ret is none, and you can print info and send it to the vendor. That is a slightly old fashioned API shape, a two element tuple where a modern client would raise, and it means the caller has to check ret on every call. The full usage guide is at developer.qiniu.com under kodo/sdk/python.

## The example set is the real API documentation

The repository's examples directory is where the breadth of the SDK becomes clear, and the file names read like a table of contents for the service. The batch operations are the largest group, with separate examples for batch, batch_copy, batch_delete, batch_move, batch_rename, batch_restoreAr and batch_stat, which is the whole family of server-side bulk operations a storage service offers. There is bucket management, with create_bucket, bucket_info, bucket_domain, change_bucket_permission, change_mime, change_status and change_type. There is the CDN group, with cdn_bandwidth, cdn_flux and cdn_log. There is file level work, with download, copy_to, delete, delete_afte_days and fops, the last being the file operation API for things like moving or copying in bulk. There are domain operations, with domain_relevant. The point of listing them is that it shows the SDK is a complete service client rather than an uploader, and that the operations which are tedious to implement by hand, the batch family in particular, are the ones with ready-made examples. The README also points at the examples directory for API usage demos, and the setup.py lists the package as name qiniu with the author Shanghai Qiniu Information Technologies Co., Ltd. and the platforms classifier as any.

## Two result conventions, and the one that catches newcomers

The FAQ is short and one of its items is about error handling, which is where a new user of this SDK will spend their first hour. The second parameter info preserves the request and response information, on failure ret is none, and you can print info and send it to the vendor. So the pattern is that every call returns a pair and the caller checks the first element, and the second element is a diagnostic object rather than an exception. There is a second failure mode the README warns about, an ImportError of No module named requests.auth, which it says to fix by installing requests, which is the kind of note that exists because the dependency is declared conditionally on the Python version. The packaging shows why. The install_requires list gates requests on python_version greater than or equal to 3.7, so on an older interpreter the dependency is not installed automatically and the import fails at runtime rather than at install time. The examples directory also includes a file named .qiniu_pythonsdk_hostscache.json, which is a cached hosts configuration for the test suite, so the tests appear to run against a real or emulated endpoint rather than a mock.

## Supported Python versions, and the packaging quirks

The runtime environment table is small and worth reading carefully. For the 7.x line of the SDK the supported Python versions are 2.7, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8 and 3.9, and for the 6.x line it is 2.7 only. The setup.py classifiers agree, listing Python 2, 2.7, 3, 3.4, 3.5, 3.6 and 3.7, and the version string itself is read out of the package rather than hardcoded, with a find_version helper that parses an __version__ assignment from qiniu/__init__.py and raises if it cannot find one. That is a deliberate choice, since it means the version in the distribution always matches the module, and it is also the kind of detail that a maintained package gets right and an unmaintained one does not. The long description is a pointer to the GitHub repository rather than the README content, and the package is published as qiniu on PyPI with both a latest stable version badge and a download count badge. The release history is steady, with v7.18.2 from 2026-07-21, v7.18.1 from 2026-07-07 and v7.18.0 from 2026-06-26, and the last push to the repository was on 2026-09-10 with the repository not archived.

## Sandbox credentials and the newer test scaffolding

The repository has a .env.example file, and it is the most informative document in the tree for anyone running the tests, because it shows what the project now expects from a test environment. It says to copy the file to .env in the project root before running sandbox examples or sandbox integration tests, and it defines a set of variables. There is a sandbox API key for sandbox auth, an optional custom endpoint, where QINIU_SANDBOX_ENDPOINT is the preferred name and QINIU_SANDBOX_API_URL and E2B_API_URL are also accepted by the SDK for compatibility. There is an optional template alias or ID that defaults to base, access key and secret key variables that are required only for the injection rule and Kodo resource examples and tests, Git credentials for the Git remote example, a GitHub token and mount path for the Git repository resource example, a Kodo bucket and mount path for the Kodo resource example, tokens for the request injection examples including an OpenAI API key, and a retry control where SANDBOX_RETRY_MAX defaults to 5 with 0 to disable. Several of these names are unfamiliar, and the presence of a sandbox concept at all, alongside an OpenAI key and a GitHub token, suggests the newer part of the project exercises code execution and repository operations rather than only storage primitives.

## Where qiniu is the wrong choice

The first limit is vendor lock-in, and it is total in the sense that matters. The package talks to Qiniu's API with Qiniu's token model, Qiniu's buckets and Qiniu's CDN, and there is no compatibility layer for S3, so a team that might switch object storage later is choosing a client that will not help them switch. The second is the error convention, and it is a design that pushes work onto every caller. Every call returns a pair, every call needs its ret checked, and the diagnostic output lives in an object rather than in an exception with a stack trace, which means a script that forgets one check will report success on a failure. A modern rewrite with a result type or exceptions would be more work for the user and less for the library, so the old shape is a legacy of the service's own API rather than an accident. The third is the Python 2.7 support, which on the 7.x line is listed alongside 3.3 to 3.9, and while running on 2.7 is a compatibility courtesy it also means the SDK cannot use modern syntax, which constrains how the code inside is written. The fourth is the documentation language, since the README is in Chinese and points at a Chinese developer site, so an English-only team is relying on the examples directory and the code itself. And the fifth is that the newest parts of the repository, the sandbox examples with their injection tokens, OpenAI keys and Git credentials, are hard to evaluate from the outside, since there is no description of what the sandbox is for, so a team reading the repository has to work that out from the variable names.

## Conclusion

Adopt qiniu if you are storing objects in Qiniu Resource Storage from Python and want the official client with its upload token flow, its batch operations and its CDN management calls rather than writing HTTP against the API by hand. Skip it if you need a client for a different object store, since this one is specific to Qiniu's API. Verify first that your Python version is in the supported range for the 7.x line, that you understand the ret and info return convention the SDK uses, and that the example set covers the operation you intend to build on.

## FAQ

### How do I install and use the qiniu Python SDK?

Install it with pip install qiniu. A typical upload creates an Auth object with an access key and secret key, mints an upload token for a bucket with q.upload_token(bucket_name), then calls qiniu.put_data with the token, a key and the payload. Every call returns a ret and info pair, where ret is none on failure and info carries the request and response details.

### Which Python versions does the qiniu SDK support?

The 7.x line of the SDK is listed as supporting Python 2.7 and 3.3 through 3.9, while the 6.x line is for Python 2.7 only. The package is published on PyPI as qiniu, and the setup.py gates the requests dependency on Python 3.7 and newer, so on an older interpreter you may need to install requests yourself.

### What operations does the qiniu SDK support beyond uploading?

The examples directory covers batch, batch_copy, batch_delete, batch_move, batch_rename, batch_restoreAr and batch_stat, bucket creation and information, domain binding, changing bucket permissions, mime type, status and type, CDN bandwidth, flux and logs, download, copy, delete, delayed deletion, file operations and domain relevance, all of which is also documented in the SDK usage guide at developer.qiniu.com.

## Sources

- [Issues](https://github.com/qiniu/python-sdk/issues)
- [License: MIT](https://github.com/qiniu/python-sdk/blob/master/LICENSE)
- [qiniu/python-sdk on GitHub](https://github.com/qiniu/python-sdk)
- [README](https://github.com/qiniu/python-sdk/blob/master/README.md)
- [Releases](https://github.com/qiniu/python-sdk/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/qiniu-python-sdk
