mrkeyoor.com_
Wed 23 Sept 09:31 UTC
PyPIUtilsupdated 23 Sept 2026

cloudpathlib review

cloudpathlib puts a pathlib-shaped API over S3, Google Cloud Storage, Azure Blob Storage, and HTTPS resources. A CloudPath can join URI segments, list object prefixes, read into a local cache, and upload changes when a file closes. Version 0.25.0 closes a cache path-traversal hole, adds lazy directory walking that callers can prune, teaches local test clients to return presigned URLs, and changes S3 metadata reads to HeadObject. Our fresh-sandbox import check was against 0.24.0, so the security fix is a reason to update rather than treat that tested build as the recommended version.

Verdict

Install cloudpathlib when path-shaped synchronous code is worth the local caching and narrower backend list. Use 0.25.0 or newer because that release fixes object keys escaping the intended cache or download directory.

We installed it

Lab card: what happened when we installed cloudpathlibScreenshot of cloudpathlib documentation
Install✓ · 0.2s1 package on disk · 1 MB
Importimport cloudpathlib in 0.39s · pure Python · py.typed · requires Python >=3.9
Known vulns0(pip-audit)

Answers from our run

Does cloudpathlib install cleanly?

Yes. In a fresh container with an empty cache, pip install cloudpathlib finished in 0.2s, leaving 1 package and 1 MB on disk. pip-audit reported no known vulnerabilities.

What does cloudpathlib need to run?

Python >=3.9, and nothing compiled: it is pure Python. In our run import cloudpathlib succeeded in 0.39s, and the package ships py.typed for type checkers.

cloudpathlib or fsspec: which should you use?

fsspec: Choose it for a larger protocol catalog, async-capable implementations, or integrations built around filesystem URLs rather than pathlib objects. Install cloudpathlib when path-shaped synchronous code is worth the local caching and narrower backend list.

When should you not use cloudpathlib?

You expect all of pathlib: the published method table excludes chmod, symlink_to, readlink, owner, cwd, home, and other local-filesystem operations

API stability3/5The current package is 0.25.0, so consumers still lack a 1.0 compatibility promise. Its central CloudPath and provider path classes deliberately resemble pathlib, and the project publishes a method matrix for the supported backends. Differences still matter: cloud writes happen around cached files, overwrite conflicts have extra flags, and methods such as walk gain cloud-specific options that standard pathlib callers will not expect.
Docs5/5The README names every install extra, explains that the base package cannot talk to a provider alone, links to authentication guidance, and lists supported methods by S3, GCS, Azure, and HTTPS. The documentation site returned HTTP 200 and has separate pages for cache modes, local test clients, credentials, S3-compatible services, and the 0.25.0 changes, including the exact behavior of lazy walking.
Maintenance5/5PyPI published 0.25.0 on August 22, 2026, and GitHub shows a push that same day. That release contains a security correction plus changes for S3 gateways, type checking, traversal, and mock clients. The repository is not archived. GitHub reports 98 open issues and pull requests together, a sizable queue, but the release work shows active response to both bug reports and new backend behavior.
Ecosystem4/5The package was assigned 7,098,795 downloads for the latest weekly window and connects to the official AWS, Google, and Azure storage SDKs through optional extras. AnyPath helps application boundaries accept local and cloud locations, while the local provider clients support unit tests. Its reach stops well short of fsspec because the README still limits implemented storage backends to S3, GCS, Azure, and HTTPS.

Use it if

  • You have functions written around pathlib operations and need them to accept S3, GCS, or Azure object URIs with limited branching
  • Downloading an object to a managed local cache is useful because a downstream tool insists on receiving a filesystem path
  • Your test suite needs LocalS3Client, LocalGSClient, or LocalAzureBlobClient in place of live cloud accounts
  • Your storage work is synchronous and mostly consists of path joins, listings, reads, writes, copies, and downloads
Skip it if

Setup reality

In our clean Python 3.12 container, cloudpathlib 0.24.0 installed in 0.2 seconds. The environment held 1 package and used 1 MB afterward. The package declared 8 direct dependencies, required Python 3.9 or newer, shipped pure Python and py.typed, and imported in 0.39 seconds. pip-audit reported no known vulnerabilities in that tested environment. Current release 0.25.0 fixes a local cache path-traversal advisory, so do not pin the measured build.

The base install does not include a working S3, GCS, or Azure SDK. Choose an extra such as cloudpathlib[s3], cloudpathlib[gs], or cloudpathlib[azure]. Authentication then follows the selected vendor SDK. That means AWS profiles or roles, Google Application Default Credentials, and Azure credentials remain separate deployment concerns. Public buckets may allow unsigned access, but a private bucket still needs the provider's normal credential chain.

Remote content lands in a local cache. A client can use a temporary directory or an explicit local_cache_dir; persistent mode never cleans that directory for you. The close_file mode only removes a cached file after a handle opened through CloudPath.open closes. If both the cached copy and cloud object changed, cloudpathlib raises and asks you to choose a force_overwrite direction.

Object prefixes only resemble directories. A broad glob or default walk can list an entire subtree, and copytree or directory downloads recurse through every child. Version 0.25.0 adds walk(lazy=True), which lists one directory at a time and permits top-down pruning. That reduces calls when you will skip branches, while the default recursive listing is faster when you need the whole tree.

Patterns

Pick a path class from the URI dispatch-from-uri

from cloudpathlib import CloudPath

report = CloudPath("s3://company-reports/2026/august.csv")
print(type(report).__name__)
print(report.bucket, report.key)

URI dispatch selects the path class, but constructing a usable provider client still requires the matching install extra.

Accept either kind of path accept-local-or-remote

from cloudpathlib import AnyPath

def read_config(location: str) -> str:
    path = AnyPath(location)
    return path.read_text(encoding="utf-8")

The same function can now perform local disk I/O or a network-backed cached read. Keep that difference visible to callers that have latency limits.

Install only the provider you use install-provider-extra

pip install "cloudpathlib[s3]"
# Other choices: cloudpathlib[gs], cloudpathlib[azure], cloudpathlib[all]

A plain cloudpathlib install supplies the base classes but not the vendor SDK needed for these concrete cloud paths.

Edit a cloud object as text read-and-write-text

from cloudpathlib import S3Path

source = S3Path("s3://documents/inbox/message.txt")
target = source.parent / "processed.txt"
target.write_text(source.read_text(encoding="utf-8").upper(), encoding="utf-8")

Both calls are synchronous. The read uses a local cached file, and the write uploads the changed file.

Use the file context manager open-a-cloud-file

from cloudpathlib import CloudPath

log = CloudPath("gs://service-logs/current.ndjson")
with log.open("rt", encoding="utf-8") as handle:
    for line in handle:
        consume(line)

open presents a normal local file handle after caching the object. It is different from iterating a provider-native response stream.

Glob below a cloud prefix list-matching-objects

from cloudpathlib import CloudPath

root = CloudPath("s3://warehouse/daily/")
for parquet_file in root.glob("2026/**/*.parquet"):
    print(parquet_file)

A recursive glob turns into remote listing work. Narrow the prefix before applying a double-star pattern on a large bucket.

Skip branches during a lazy walk prune-a-cloud-walk

from cloudpathlib import CloudPath

root = CloudPath("s3://warehouse/")
for directory, dirnames, filenames in root.walk(top_down=True, lazy=True):
    dirnames[:] = [name for name in dirnames if name != "archive"]
    for name in filenames:
        print(directory / name)

lazy=True was added in 0.25.0. It lists directories on demand, so pruning dirnames prevents listings inside the skipped branch.

Download an object to a local path download-to-disk

from pathlib import Path
from cloudpathlib import CloudPath

remote = CloudPath("azure://exports/monthly/report.pdf")
local = remote.download_to(Path("artifacts/report.pdf"))
print(local)

Version 0.25.0 checks that object keys cannot escape the chosen download directory through parent segments or Windows path tricks.

Copy a local tree into storage upload-a-directory

from cloudpathlib import CloudPath

destination = CloudPath("gs://static-site/releases/2026-08/")
uploaded = destination.upload_from("dist")
print(uploaded)

A directory upload recurses through the local tree. Review the destination prefix and overwrite behavior before using it in a deployment job.

Attach an explicit S3 client select-an-aws-profile

from cloudpathlib import S3Client, S3Path

client = S3Client(profile_name="analytics-prod")
report = S3Path("s3://private-data/latest.csv", client=client)
print(report.read_text(encoding="utf-8"))

The named profile is resolved by boto3. Keep secrets out of source and let the normal profile, role, or environment chain supply them.

Choose where cached files live keep-a-persistent-cache

from cloudpathlib import FileCacheMode, S3Client

client = S3Client(
    local_cache_dir="/var/tmp/cloud-files",
    file_cache_mode=FileCacheMode.persistent,
)
path = client.CloudPath("s3://media/original.mov")

Persistent mode requires local_cache_dir and leaves cleanup to your process or an external disk policy.

Replace S3 with local fixtures test-with-local-s3

from pathlib import Path
from cloudpathlib.local import LocalS3Client

client = LocalS3Client(local_storage_dir=Path("tests/storage"))
fixture = client.CloudPath("s3://fixtures/input.txt")
assert fixture.read_text(encoding="utf-8") == "hello"

The local client exercises cloudpathlib calls, including mock presigned URLs in 0.25.0. It does not reproduce IAM, provider throttling, or every S3 error.

Alternatives

PackageRegistryPick it when
fsspecPyPIChoose it for a larger protocol catalog, async-capable implementations, or integrations built around filesystem URLs rather than pathlib objects
s3fsPyPIChoose it when the target is only S3 and pandas, Dask, or another fsspec consumer drives the design
smart-openPyPIChoose it when the main job is opening a large remote stream without keeping a pathlib-style local cache
universal-pathlibPyPIChoose it when pathlib syntax matters but the backend needs to come from fsspec's wider filesystem set

More utils guides

lru-cache · ajv · type-fest · p-limit · find-up · js-yaml · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.