Skip to main content

Retrieve baseball data in Python

Project description

polars-baseball

Languages: English | Traditional Chinese

polars-baseball is a modern asynchronous Python library for retrieving baseball data. It is built around Polars, where most public data APIs return polars.DataFrame objects (with documented exceptions such as standings() returning other shapes), and supports Statcast, Baseball Reference, FanGraphs, Lahman, Retrosheet, MLB Stats API, and player ID workflows.


Key Features

  • Polars Core: Most public APIs return native polars.DataFrame objects (with standings() returning list[polars.DataFrame]) for filtering, aggregation, and export.
  • Async-First Engine: Data-fetching APIs are asynchronous and should be called with await or asyncio.run().
  • Flexible Concurrency: Support for custom context configuration to isolate resources in multi-threaded/loop environments.
  • Automatic Cache: Built-in file caching reduces repeated network requests for large workflows.

Installation

pip install polars-baseball

For local development:

git clone https://github.com/nicko4o/polars-baseball
cd polars-baseball
uv sync --all-extras

To run the visualization examples, install the optional example dependencies:

pip install "polars-baseball[plot]"

Quick Start

1. Statcast Queries

import asyncio

import polars_baseball as pb


async def main() -> None:
    df = await pb.statcast(start_dt="2024-05-06", end_dt="2024-05-06")
    print(df.head(5))

    darvish_df = await pb.statcast_pitcher(
        start_dt="2024-05-06",
        end_dt="2024-05-06",
        player_id=450314,
    )
    print(darvish_df.head(5))


if __name__ == "__main__":
    asyncio.run(main())

2. Aggregate with Polars

import asyncio

import polars as pl
import polars_baseball as pb


async def main() -> None:
    darvish_df = await pb.statcast_pitcher(
        start_dt="2024-05-06",
        end_dt="2024-05-06",
        player_id=450314,
    )
    summary = (
        darvish_df
        .group_by("pitch_type")
        .agg(pl.col("release_speed").mean().alias("mean_speed"))
    )
    print(summary)


if __name__ == "__main__":
    asyncio.run(main())

3. Top Prospects

import asyncio

import polars_baseball as pb


async def main() -> None:
    prospects = await pb.top_prospects(team_name="mets")
    print(prospects.head(5))


if __name__ == "__main__":
    asyncio.run(main())

4. Interactive Data Visualization

polars-baseball does not provide a plotting API. This example passes the returned polars.DataFrame to hvPlot.

import asyncio

import hvplot.polars  # noqa: F401
import polars_baseball as pb


async def main() -> None:
    df = await pb.statcast(start_dt="2024-05-06", end_dt="2024-05-06")
    chart = (
        df
        .filter(df["hc_x"].is_not_null() & df["hc_y"].is_not_null())
        .plot.scatter(
            x="hc_x",
            y="hc_y",
            by="events",
            invert_y=True,
        )
    )
    print(chart)


if __name__ == "__main__":
    asyncio.run(main())

Web Services & Concurrency (FastAPI, Gunicorn, Celery)

By default, calling package functions without a context parameter will fallback to an implicit package-level global singleton BaseballContext. This global default context is not guaranteed to be thread-safe or loop-safe in long-running concurrent environments.

When deploying polars-baseball inside concurrent web services (such as FastAPI, Gunicorn, or Celery workers), you must explicitly manage the lifespan of BaseballContext and pass it to all API calls.

FastAPI lifespan Example

from contextlib import asynccontextmanager
from fastapi import FastAPI
import polars_baseball as pb

@asynccontextmanager
async def lifespan(app: FastAPI):
    # Initialize a dedicated context bound to the app's event loop
    app.state.pb_context = pb.BaseballContext()
    try:
        yield
    finally:
        # Properly clean up HTTP connections
        await app.state.pb_context.http.close()

app = FastAPI(lifespan=lifespan)

@app.get("/statcast")
async def get_statcast():
    df = await pb.statcast(
        start_dt="2026-06-01",
        end_dt="2026-06-02",
        context=app.state.pb_context,
    )
    return df.to_dicts()

API Namespace Policy

The package root (import polars_baseball as pb) exposes only the stable, commonly used public API. Provider-specific and advanced functions remain available from polars_baseball.apis.*.

Modules prefixed with _, including _schemas, are internal implementation details and are not part of the compatibility contract.


Documentation


Contributing

See CONTRIBUTING.md for the development workflow and architecture notes.


Author

Created and maintained by Nick.

Project details


Download files

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

Source Distribution

polars_baseball-0.1.0.tar.gz (105.3 kB view details)

Uploaded Source

Built Distribution

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

polars_baseball-0.1.0-py3-none-any.whl (133.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: polars_baseball-0.1.0.tar.gz
  • Upload date:
  • Size: 105.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for polars_baseball-0.1.0.tar.gz
Algorithm Hash digest
SHA256 9760334ba41a2d67280707245691a30c419f400a0d3f1ce2693e66d513aeff98
MD5 4720bae897deb88a732830d3fc73abb7
BLAKE2b-256 db986a4fef1e85cddca28f28fb9c2dc9fd6f9d33977a635e0987c96defcec46e

See more details on using hashes here.

File details

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

File metadata

  • Download URL: polars_baseball-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 133.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for polars_baseball-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7f1e12607c7972b5bb4d2705c4ec59aa729b255f5bbbcea15a2e2ba26a478fc5
MD5 1bb875c34c6fa1bce92585d4ea72f512
BLAKE2b-256 7ae317a62b395b40028e3f03ae52f9723b5e7406612ecd9f49c162fd1776f57b

See more details on using hashes here.

Supported by

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