This release is a pre-release and may not be stable for production use.
gs_fastcopy (python)
Optimized file copying & compression for large files on Google Cloud Storage.
TLDR:
import gs_fastcopy
import numpy as np
with gs_fastcopy.write('gs://my-bucket/my-file.npz') as f:
np.savez(f, a=np.zeros(12), b=np.ones(23))
with gs_fastcopy.read('gs://my-bucket/my-file.npz') as f:
npz = np.load(f)
a = npz['a']
b = npz['b']
Provides file-like interfaces for:
- Parallel, XML multipart uploads to Cloud Storage.
- Parallel, sliced downloads from Cloud Storage using
gcloud storage. - Parallel (de)compression using
pigzandunpigzif available (with fallback to standardgzipandgunzip).
Together, these provided ~70% improvement on uploading a 1.2GB file, and ~40% improvement downloading the same.
Examples
gs_fastcopy is easy to use for reading and writing files.
You can use it without compression:
with gs_fastcopy.write('gs://my-bucket/my-file.npz') as f:
np.savez(f, a=np.zeros(12), b=np.ones(23))
with gs_fastcopy.read('gs://my-bucket/my-file.npz') as f:
npz = np.load(f)
a = npz['a']
b = npz['b']
gs_fastcopy also handles gzip compression transparently. Note that we don't use numpy's savez_compressed:
with gs_fastcopy.write('gs://my-bucket/my-file.npz.gz') as f:
np.savez(f, a=np.zeros(12), b=np.ones(23))
with gs_fastcopy.read('gs://my-bucket/my-file.npz.gz') as f:
npz = np.load(f)
a = npz['a']
b = npz['b']
Caveats & limitations
-
You need a
__main__guard.Subprocesses spawned during parallel processing re-interpret the main script. This is bad if the main script then spawns its own subprocesses…
See also gs-fastcopy-python#5 with a further note on freezing scripts into executables.
-
You need a filesystem.
Because
gs_fastcopyuses tools that work with files, it must be able to read/write a filesystem, in particular temporary files as set up bytempfile.TemporaryDirectory()[python docs].This is surprisingly versatile: even "very" serverless environments like Cloud Functions present an in-memory file system.
-
You need the
gcloudSDK on your path.Or, at least the
gcloud storagecomponent of the SDK.gs_fastcloudusesgcloudto download files.Issue #2 considers falling back to Python API downloads if the specialized tools aren't available.
-
You need enough disk space for the compressed & uncompressed files, together.
Because
gs_fastcloudwrites the (un)compressed file to disk while (de)compressing it, the file system needs to accommodate both files while the operation is in progress.- Reads from Cloud: (1) fetch to temp file; (2) decompress if gzipped; (3) stream temp file to Python app via
read(); (4) delete the temp file - Writes to Cloud: (1) app writes to temp file; (2) compress if gzipped; (3) upload temp file to Google Cloud; (4) delete the temp file
- Reads from Cloud: (1) fetch to temp file; (2) decompress if gzipped; (3) stream temp file to Python app via
Why gs_fastcopy
APIs for Google Storage (GS) typically present File-like interfaces which read/write data sequentially. For example: open up a stream then write bytes to it until done. Data is streamed between cloud storage and memory. It's easy to use stream-based compression like gzip along the way.
Libraries like smart_open add yet more convenience, providing a unified interface for reading/writing local files and several cloud providers, with transparent encryption for .gz files. Quite delightful!
Unfortunately, these approaches are single-threaded. We noticed that transfer time for files sized many 100s of MBs was lower than expected. @lynnlangit pointed me toward the composite upload feature in gcloud storage cp. A "few" hours later, gs_fastcopy came to be.
Why both gcloud and XML multi-part
I'm glad you asked! I initially implemented this just with gcloud's composite uploads. But the documentation gave a few warnings about composite uploads.
Basically, composite uploads leverage independent API functions, whereas XML multi-part is a managed operation. The managed operation plays more nicely with other features like retention policies. On the other hand, because it's separate, the XML multi-part API needs additional permissions. (We may need to fall back to gcloud in that case!)
On top of being "weird" in these ways, composite uploads are actually slower. I found this wonderful benchmarking by Christopher Madden: High throughput file transfers with Google Cloud Storage (GCS). TLDR, gcloud sliced downloads outperform the Python API, but for writes the XML multi-part API is best. (By far, if many cores are available.)
Metadata
Release files for gs-fastcopy 1.0a7
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| gs_fastcopy-1.0a7.tar.gz | 11.5 kB | Without provenance | Details for gs_fastcopy-1.0a7.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| gs_fastcopy-1.0a7-py3-none-any.whl | Python 3 | none | any | Details for gs_fastcopy-1.0a7-py3-none-any.whl |
Total release size: 20.3 kB
Release files / gs_fastcopy-1.0a7.tar.gz
| Download URL | gs_fastcopy-1.0a7.tar.gz |
|---|---|
| Size | 11.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3e3ddc67272314845231d1f4cdff4682585d925f43fd3bb3cbfba580f58b656b
|
|
BLAKE2b-256 checksum How to use checksums |
e4b3f475ae2a8b5a199664673f963ee353d783c5b1b46fed1c9a87f82856f3e1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.6
|
Release files / gs_fastcopy-1.0a7-py3-none-any.whl
| Download URL | gs_fastcopy-1.0a7-py3-none-any.whl |
|---|---|
| Size | 8.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b5ab010fd09b6f6d7c948ed0e2e1022a944506bdba5a1fd19dfdb1ef99728819
|
|
BLAKE2b-256 checksum How to use checksums |
a73c2d6565f951695760812ae54bc0e3e78a429cba8e86679a339408013425eb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.6
|
Security for gs-fastcopy 1.0a7
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.