Skip to main content

PyPI version Python License

read-google-sheet

Load public Google Sheets directly into Polars LazyFrame or DataFrame — with railway-oriented error handling via polars-result.

Requires Python 3.14+

Features

  • 📊 Polars-native — returns LazyFrame by default, DataFrame on request
  • 🚂 Railway-oriented — every operation returns Result[T, Exception], never raises
  • ✅ Validated — sheet ID and name are validated before any network request
  • 📦 Minimal dependencies — Polars, requests, polars-result

Installation

uv add read-google-sheet
pip install read-google-sheet

Quick Start

from polars_result import Ok, Err
from read_google_sheet import read_google_sheet

result = read_google_sheet(
    sheet_id="1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms",
    sheet_name="Sheet1",
)

match result:
    case Ok(lf):
        print(lf.collect())
    case Err(e):
        print(f"Failed: {e}")

API Reference

read_google_sheet

def read_google_sheet(
    sheet_id: str,
    sheet_name: str,
    as_dataframe: bool = False,
    parse_dates: bool = True,
) -> Result[pl.LazyFrame | pl.DataFrame, Exception]
Parameter Description
sheet_id 44-character Google Sheet ID from the sheet URL
sheet_name Tab name within the spreadsheet
as_dataframe Return a collected DataFrame instead of a LazyFrame
parse_dates Attempt to parse date columns automatically

GoogleSheetConfig

Low-level dataclass for direct access and step-by-step control:

from read_google_sheet import GoogleSheetConfig

config = GoogleSheetConfig(
    sheet_id="1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms",
    sheet_name="Sheet1",
    timeout=10,
)

result = config.to_lazyframe()    # Result[pl.LazyFrame, Exception]
result = config.to_dataframe()    # Result[pl.DataFrame, Exception]
url    = config.create_url()      # Result[str, Exception]
data   = config.fetch_data()      # Result[StringIO, Exception]

Exceptions

All exceptions inherit from GoogleSheetError:

Exception Raised when
ConfigurationError Invalid sheet ID or empty sheet name
SheetFetchError HTTP request fails or returns a non-200 status
NetworkError Connection error or timeout
SheetTransformError CSV parsing or LazyFrame collection fails
ValidationError General validation failure

Error Handling Patterns

Pattern 1: Match on result

from read_google_sheet import read_google_sheet, ConfigurationError, NetworkError

match read_google_sheet(sheet_id="...", sheet_name="Sheet1"):
    case Ok(lf):
        df = lf.collect()
    case Err(ConfigurationError() as e):
        print(f"Config problem: {e}")
    case Err(NetworkError() as e):
        print(f"Network problem: {e}")
    case Err(e):
        print(f"Unexpected error: {e}")

Pattern 2: Chain operations

import polars as pl
from polars_result import Ok
from read_google_sheet import read_google_sheet

result = (
    read_google_sheet(sheet_id="...", sheet_name="Sheet1")
    .map(lambda lf: lf.filter(pl.col("amount") > 0))
    .map(lambda lf: lf.select("vessel", "service", "amount"))
    .and_then(lambda lf: Ok(lf.collect()))
)

Pattern 3: Fallback to another sheet

result = (
    read_google_sheet(sheet_id="...", sheet_name="live")
    .or_else(lambda _: read_google_sheet(sheet_id="...", sheet_name="backup"))
    .unwrap_or(pl.LazyFrame())
)

Pattern 4: Unwrap with default

lf = read_google_sheet(sheet_id="...", sheet_name="Sheet1").unwrap_or(pl.LazyFrame())

Usage in Marimo Notebooks

import marimo as mo
from polars_result import Ok, Err
from read_google_sheet import read_google_sheet

result = read_google_sheet(
    sheet_id="1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms",
    sheet_name="Sheet1",
    as_dataframe=True,
)

match result:
    case Ok(df):
        mo.ui.table(df)
    case Err(e):
        mo.callout(mo.md(f"**Failed to load sheet:** {e}"), kind="danger")

How It Works

The package uses Google Sheets' public CSV export endpoint — no API key or OAuth required. The sheet must be set to "Anyone with the link can view".

The URL format used internally:

https://docs.google.com/spreadsheets/d/{sheet_id}/gviz/tq?tqx=out:csv&sheet={sheet_name}

Development

uv sync                                                           # install dependencies
uv run pytest                                                     # run tests
uv run pytest --cov=src/read_google_sheet --cov-report=html      # with coverage
uv run ruff check src/ tests/                                     # lint
uv run ruff format src/ tests/                                    # format
uv run ty check                                                   # type check

Contributing

Contributions welcome — please open an issue or PR on GitHub.

License

MIT — see LICENSE for details.

Metadata

Release files for read-google-sheet 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for read-google-sheet 0.1.0
File Size Uploaded
read_google_sheet-0.1.0.tar.gz 36.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for read-google-sheet 0.1.0
File Interpreter ABI Platform
read_google_sheet-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 45.3 kB

Release files / read_google_sheet-0.1.0.tar.gz

Download URL read_google_sheet-0.1.0.tar.gz
Size 36.0 kB
Tags Source
SHA-256 checksum
How to use checksums
3c7dce25de32419d6351a91d7a3314f96b19871973165719d8119736748f10a8
BLAKE2b-256 checksum
How to use checksums
b4d1d9db83b5e555d7a24e28ed165eb538e77db9844fca065bf050e52d3246e2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / read_google_sheet-0.1.0-py3-none-any.whl

Download URL read_google_sheet-0.1.0-py3-none-any.whl
Size 9.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9b7ece7bb6fb08fbda14cafb608a34a8fcb1ca793ede538cba3e34524bbaa656
BLAKE2b-256 checksum
How to use checksums
13bdb3525dfe7ed11d66480263f9f20a7bf753a856339d35891baa13086fc866
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

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