pypi / pyathena
pyathena
What changed in pyathena 3 to 4, from its official release notes, upgrade guides and advisories. Sources checked 2026-10-25.
21 breaking2 new APIs and options2 performance3 behavior and defaults6 fixes and other
See which of these apply to your code, ranked, in your agent:
npx @unstale/cli initpyathena 431 changes
Breaking changes 20
Blocking calls run in filesystem and per-file pools of up to max_workers threads instead of the event loop's default executor; non-positive values raise ValueError.
CSV dates are now read as date32 instead of timestamp[ms]; as_polars() returns pl.Date.
AioPandasCursor.as_pandas() is now a coroutine, must be awaited, and always returns a DataFrame.
After closing an AsyncCursor, pending execute(), description(), and poll() futures raise ProgrammingError; the query is not cancelled.
description(query_id) now reads result metadata or an UNLOAD Parquet schema without reading result rows; custom result sets must customize their metadata reader instead.
Methods on a closed cursor now raise ProgrammingError("Cursor is closed.") instead of returning empty values or running a new query.
Fetch, iteration, conversion, and chunk methods on a closed result set now raise ProgrammingError instead of returning empty results.
Conversion failures in every cursor now raise DataError naming the column; pandas whole reads no longer wrap that failure in OperationalError.
After a fetch fails, subsequent fetchone(), fetchmany(), and fetchall() calls raise ProgrammingError; invalid arguments do not count as failed fetches.
Polars 2.0 describes UNLOAD map columns as map with dict values, and ArrowCursor.as_polars() returns them as pl.Map.
Calling next() on an asyncio cursor or result set now raises TypeError rather than returning an un-awaited coroutine.
Failed reads of UNLOAD manifests and Spark calculation output now raise OperationalError instead of botocore exceptions.
Temporal dtypes now depend only on the Athena type: timestamps use microseconds, zoned timestamps use UTC, and UNLOAD dates use datetime64[us].
With Polars 2.0, new_columns used together with schema_overrides must name every column; a schema passed to execute() is used as given.
Multipart writes keep at most max_workers parts in flight; failures surface on the next write(), flush(), or close(), which closes without committing.
commit() raises S3MultipartStateError after discard() or a failed write or commit.
S3File.multipart_upload is now read-only.
S3File.multipart_upload_parts has been removed.
With the default flavor="spark", table column names replace spaces, tabs, newlines, and ,;{}()= with underscores to match Parquet names.
tzdata>=2024.2 is required for timestamp with time zone values; unknown or ambiguous daylight-saving zones now raise DataError.
New APIs and options 2
Cursors now expose an is_closed property.
AioPandasCursor and AioPolarsCursor add async iter_chunks() for reading chunks one at a time.
Performance 2
With Polars 1.x, unchunked CSV reads no longer hold a second copy of the result file, reducing peak memory to the level of 4.1.0.
Temporal values are converted faster across Cursor, DictCursor, S3FSCursor, ArrowCursor, PolarsCursor, and PandasCursor reads.
Behavior and default changes 3
For unchunked CSV reads, a non-UTF-8 encoding is not decoded and causes OperationalError, matching 4.1.0 behavior.
Temporal converters now use fromisoformat(), accepting more ISO 8601 forms; text from other sources that previously raised ValueError now converts.
threadsafety = 2 declares that calling one cursor or result set from several threads is not supported; use the query ID to stop a query from another thread.
Fixes and other changes 4
PandasCursor no longer fails when parse_dates omits a time column or index_col names a time column.
Python 3.15 is now supported.
completed_parts returns uploaded or copied parts in part-number order.
PandasCursor, ArrowCursor, and PolarsCursor read UNLOAD timestamps at microsecond precision at every nesting level, including chunked reads.
pyathena 33 changes
Breaking changes 1
Cursor descriptions report Polars 2.0 UNLOAD map columns as map, and structs containing lists as row; with Polars 1.x, maps remain array.
Fixes and other changes 2
With unload=true, connection pings no longer fail with MISSING_COLUMN_NAME; they run SELECT 1 through a plain Cursor while SQLAlchemy retains its failed-ping handling.
PolarsCursor and AioPolarsCursor work with Polars 2.0: CSV results are read through PyAthena's S3 filesystem and passed to Polars as bytes, also supporting Polars 1.x.