Skip to main content

read-sheet

Read public Google Sheets into Polars DataFrames and LazyFrames — no auth, no service accounts, no API keys.

PyPI Python License: MIT CI


Requirements

  • Python ≥ 3.13
  • The spreadsheet must be set to Anyone with the link can view

Installation

pip install scan-google-sheet
# or
uv add scan-google-sheet

Quick start

from scan_google_sheet import read_google_sheet, scan_google_sheet

Eager — returns a DataFrame immediately:

df = read_google_sheet("Sheet1", sheet_id="1BxiMVs0XRA5nFMdKvBdBZjgm...")

Lazy — returns a LazyFrame, participates in Polars query optimisation:

lf = scan_google_sheet("Sheet1", sheet_id="1BxiMVs0XRA5nFMdKvBdBZjgm...")

df = (
    lf
    .filter(pl.col("year") == 2025)
    .select("vessel", "amount")
    .collect()
)

You can also pass a full Google Sheets URL instead of a bare sheet ID:

df = read_google_sheet(
    "Sheet1",
    url="https://docs.google.com/spreadsheets/d/1BxiMVs0.../edit#gid=0",
)

API

read_google_sheet

def read_google_sheet(
    sheet_name: str,
    sheet_id: str | None = None,
    url: str | None = None,
    *,
    timeout: int = 10,
    parse_dates: bool = True,
) -> pl.DataFrame

Fetches the sheet and returns a collected DataFrame. Use this when you want the data immediately and do not need lazy evaluation.

scan_google_sheet

def scan_google_sheet(
    sheet_name: str,
    sheet_id: str | None = None,
    url: str | None = None,
    *,
    timeout: int = 10,
    parse_dates: bool = True,
    batch_size: int = 1_000,
) -> pl.LazyFrame

Returns a LazyFrame registered via the Polars IO plugin API. Projection pushdown, predicate pushdown, head(), and streaming are all supported.

Note: Google Sheets does not support partial HTTP reads. The full sheet is always downloaded in one request. Pushdowns reduce processing cost, not network cost.

Parameters shared by both functions:

Parameter Type Default Description
sheet_name str Tab name as shown in Google Sheets
sheet_id str | None None Spreadsheet ID from the URL
url str | None None Full Google Sheets URL (ID extracted automatically)
timeout int 10 HTTP timeout in seconds
parse_dates bool True Attempt automatic date/datetime parsing

Provide either sheet_id or url, not both.


URL utilities

from scan_google_sheet import extract_sheet_id, build_gviz_url, from_url

# Extract the sheet ID from any Google Sheets URL
sheet_id = extract_sheet_id("https://docs.google.com/spreadsheets/d/ABC123/edit")
# "ABC123"

# Build a gviz CSV export URL from a sheet ID and tab name
url = build_gviz_url("ABC123", "Sheet1")
# "https://docs.google.com/spreadsheets/d/ABC123/gviz/tq?tqx=out:csv&sheet=Sheet1"

# Build a gviz URL directly from a full Google Sheets URL
url = from_url("https://docs.google.com/spreadsheets/d/ABC123/edit", "Sheet1")

Error handling

All exceptions inherit from ReadSheetError, so you can catch everything with one handler or branch on specific types:

from scan_google_sheet import (
    read_google_sheet,
    ReadSheetError,
    SheetFetchError,
    SheetURLError,
    SheetParseError,
    NetworkError,
    ConfigurationError,
)

try:
    df = read_google_sheet("Sheet1", sheet_id="...")
except ReadSheetError as e:
    match e:
        case SheetFetchError() if e.is_auth_error:
            print("Make the sheet public (Share → Anyone with the link)")
        case SheetFetchError() if e.is_not_found:
            print(f"Sheet not found — check the ID: {e.url}")
        case NetworkError():
            print(f"No connection: {e.cause}")
        case SheetURLError(raw=r):
            print(f"Could not parse URL: {r!r}")
        case SheetParseError():
            print(f"CSV parse failed: {e.cause}")
        case ConfigurationError():
            print(str(e))

Exception hierarchy

ReadSheetError
├── SheetURLError       malformed URL or unextractable sheet ID  (.raw)
├── SheetFetchError     non-200 HTTP response                    (.url, .status_code)
│                                                                (.is_auth_error, .is_not_found)
├── SheetParseError     CSV or Polars parsing failure            (.column)
├── NetworkError        transport failure, no response received  (.url)
└── ConfigurationError  invalid argument combination

Making your sheet public

In Google Sheets: Share → Change to Anyone with the link → Viewer → Done.

The export URL used by this library (gviz/tq?tqx=out:csv) requires the sheet to be publicly readable. No data is ever written.


How it works

Google Sheets URL / ID
        │
        ▼
  build_gviz_url()          constructs the CSV export URL
        │
        ▼
    fetch_raw()             httpx GET with follow_redirects=True
        │
        ▼
  pl.scan_csv()             parsed into a Polars LazyFrame
        │
        ▼
register_io_source()        registered as a Polars IO plugin
        │
        ▼
  LazyFrame / DataFrame     ready for your pipeline

Development

git clone https://github.com/Attica-oss/scan_google_sheet
cd scan_google_sheet
uv sync --group dev
uv run pytest

Lint and format:

uv run ruff check src/ tests/
uv run ruff format src/ tests/
uv run ty check src/

Changelog

0.1.0 (2025)

  • Initial release
  • read_google_sheet and scan_google_sheet
  • Polars IO plugin for lazy evaluation
  • Structured exception hierarchy
  • Full test suite with pytest-httpx

License

MIT © 2025 Attica-oss

Download files

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

Source Distribution

scan_google_sheet-0.1.1.tar.gz (9.3 kB view details)

Uploaded Source

Built Distribution

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

scan_google_sheet-0.1.1-py3-none-any.whl (12.5 kB view details)

Uploaded Python 3

File details

Details for the file scan_google_sheet-0.1.1.tar.gz.

File metadata

  • Download URL: scan_google_sheet-0.1.1.tar.gz
  • Upload date:
  • Size: 9.3 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 scan_google_sheet-0.1.1.tar.gz
Algorithm Hash digest
SHA256 a3c13e1609723432df3ce0d5a07007573b96271cbfee14c9efa08e21f5713860
MD5 29418aed529da63360babc7f3c8d798e
BLAKE2b-256 bb2aa7469c2e73d2f080125039d3bab11e112a0e8914cd6f386cc536423df2b8

See more details on using hashes here.

File details

Details for the file scan_google_sheet-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: scan_google_sheet-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 12.5 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 scan_google_sheet-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b6421781cf0ec2b0688444f41ae299e0ed766268695bd762570b9a94ae321f32
MD5 97540dd5a6a7a1bbf99016a28964b9c7
BLAKE2b-256 9c2f5c70ab3fa826e4108305e04524b9074b2e95c79681d0aa41d27de4dfc93a

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 files

0.1.0

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