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.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

read_google_sheet-0.1.0.tar.gz (36.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

read_google_sheet-0.1.0-py3-none-any.whl (9.3 kB view details)

Uploaded Python 3

File details

Details for the file read_google_sheet-0.1.0.tar.gz.

File metadata

  • Download URL: read_google_sheet-0.1.0.tar.gz
  • Upload date:
  • Size: 36.0 kB
  • Tags: Source
  • Uploaded using 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}

File hashes

Hashes for read_google_sheet-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3c7dce25de32419d6351a91d7a3314f96b19871973165719d8119736748f10a8
MD5 746fcc3ed407ae094b8fa0cd5ab9d7b8
BLAKE2b-256 b4d1d9db83b5e555d7a24e28ed165eb538e77db9844fca065bf050e52d3246e2

See more details on using hashes here.

File details

Details for the file read_google_sheet-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: read_google_sheet-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 9.3 kB
  • Tags: Python 3
  • Uploaded using 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}

File hashes

Hashes for read_google_sheet-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9b7ece7bb6fb08fbda14cafb608a34a8fcb1ca793ede538cba3e34524bbaa656
MD5 d63d5a324a526d9e52b97adb5454f8dc
BLAKE2b-256 13bdb3525dfe7ed11d66480263f9f20a7bf753a856339d35891baa13086fc866

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page