Skip to main content
Pre-release

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 pigz and unpigz if available (with fallback to standard gzip and gunzip).

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_fastcopy uses tools that work with files, it must be able to read/write a filesystem, in particular temporary files as set up by tempfile.TemporaryDirectory() [python docs].

    This is surprisingly versatile: even "very" serverless environments like Cloud Functions present an in-memory file system.

  • You need the gcloud SDK on your path.

    Or, at least the gcloud storage component of the SDK.

    gs_fastcloud uses gcloud to 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_fastcloud writes 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

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)

Source distribution for gs-fastcopy 1.0a7
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)

Table of built distributions (wheels) for gs-fastcopy 1.0a7
File Interpreter ABI Platform Actions
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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page