Pathy: Cloud-Agnostic Pathlib
Pathy extends Python's `pathlib.Path` to provide a unified, pathlib-compatible interface for interacting with local filesystems and various cloud storage services (S3, GCS, Azure Blob Storage). It aims to make file operations cloud-agnostic and seamless. The current stable version is 0.13.0, with frequent minor and patch updates.
Warnings
- breaking Pathy no longer inherits directly from `pathlib.Path`. This means some methods or properties specific to `pathlib.Path` might behave differently or be unavailable, and direct `isinstance(pathy_obj, pathlib.Path)` checks will fail.
- breaking The `Pathy.key` property now returns a `str` instead of a `Pathy` instance. This changes the type of the key used to represent the path's identifier within a bucket or root.
- breaking The `Pathy.stat()` method now consistently returns a `pathy.BlobStat` object for both local and remote paths. Previously, local paths would return an `os.stat_result`.
- breaking Dropped support for Python 3.7. Pathy now requires Python 3.10 or newer.
- breaking Pathy's internal architecture, relying on `pathlib_abc`, underwent significant upgrades (0.3.x to 0.5.x). While primarily internal, users extending Pathy or relying on deep internal interfaces might experience breaking changes.
- gotcha Cloud provider support requires specific 'extras' to be installed (e.g., `pathy[s3]`, `pathy[gcs]`, `pathy[azure]`). Without these, attempts to access cloud paths will result in import errors or `ClientError`.
Install
-
pip install pathy -
pip install "pathy[s3]" -
pip install "pathy[gcs]" -
pip install "pathy[azure]"
Imports
- Pathy
from pathy import Pathy
- BlobStat
from pathy import BlobStat
Quickstart
from pathy import Pathy
import os
# --- Local filesystem operations ---
local_file_path = Pathy("./temp_pathy_local_file.txt")
try:
local_file_path.write_text("Hello from Pathy on local filesystem!")
print(f"Local file content: '{local_file_path.read_text()}'")
print(f"Local file size: {local_file_path.stat().st_size} bytes")
finally:
if local_file_path.exists():
local_file_path.unlink() # Clean up
# --- Cloud storage operations (example: S3) ---
# Replace with your bucket name and ensure AWS credentials are set as environment variables
s3_bucket = os.environ.get("PATHY_TEST_S3_BUCKET", "my-pathy-test-bucket")
s3_path = Pathy(f"s3://{s3_bucket}/example_dir/cloud_data.txt")
# Check if AWS credentials are likely available
if os.environ.get("AWS_ACCESS_KEY_ID") and os.environ.get("AWS_SECRET_ACCESS_KEY"):
print(f"\nAttempting S3 operations on: {s3_path}")
try:
# Create parent directories (no-op if they exist for cloud paths)
s3_path.parent.mkdir(parents=True, exist_ok=True)
s3_path.write_text("Hello from Pathy on S3!")
print(f"S3 file content: '{s3_path.read_text()}'")
print(f"S3 file size: {s3_path.stat().st_size} bytes")
except Exception as e:
print(f"Failed to perform S3 operations. Ensure 'pathy[s3]' is installed and credentials are correct. Error: {e}")
finally:
if s3_path.exists():
s3_path.unlink() # Clean up
print(f"Cleaned up S3 file: {s3_path}")
else:
print("\nSkipping S3 example: AWS_ACCESS_KEY_ID and/or AWS_SECRET_ACCESS_KEY environment variables not set.")
print("Install 'pathy[s3]' and configure AWS credentials to run this example.")