-
Notifications
You must be signed in to change notification settings - Fork 116
Avoid Pandas JSON dtype warnings by defaulting to whole-chunk parsing #1080
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -552,10 +552,18 @@ cursor.execute("SELECT * FROM typed_table", | |
| Common performance options: | ||
|
|
||
| - `engine`: CSV parsing engine ('auto', 'c', 'python', 'pyarrow'); 'auto' uses the C engine | ||
| - `low_memory`: Parse the file in internal chunks to reduce memory use (C engine only; pandas default `True`) | ||
| - `low_memory`: Parse the file in internal chunks to reduce memory use (C engine only) | ||
| - `dtype`: Explicit column data types | ||
| - `parse_dates`: Columns to parse as dates | ||
|
|
||
| When the C engine's converter mapping includes PyAthena's JSON converter, `low_memory` defaults to `False`. | ||
| This avoids pandas' `DtypeWarning` when JSON numbers or booleans and NULLs occur in different internal parser blocks. | ||
| The setting applies to the entire CSV read, including other columns whose dtypes pandas infers. | ||
| Parsing each result or chunk at once can use more memory; `chunksize` still limits the rows read per chunk. | ||
| An explicit `low_memory=True` or `low_memory=False` passed to `execute()` takes precedence. | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Self-review round two (claims, compatibility, operations): CLEAN. Full diff: |
||
| With `low_memory=True`, the warning can return. | ||
| Without PyAthena's JSON converter, the C engine keeps pandas' default `low_memory=True`. | ||
|
|
||
| With `engine="pyarrow"`, PandasCursor uses the PyArrow engine only when the result is not a tab-separated `.txt` file, pyarrow is installed, no chunksize is set (explicitly or by `auto_optimize_chunksize`), `quoting` is the default, the result has no columns that need a converter (`boolean`, `decimal`, `varbinary`, `json`, `time with time zone`, and `timestamp with time zone` with the default converter), and the result file is at least `AthenaPandasResultSet.PYARROW_MIN_FILE_SIZE_BYTES` bytes. | ||
| Otherwise, it falls back to the C engine. | ||
| With `engine="pyarrow"`, tab-separated `.txt` results from DDL statements such as `SHOW TABLES`, `SHOW COLUMNS`, and `DESCRIBE` use the C engine to preserve leading zeros, exponent notation, and padding in string values. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -899,6 +899,12 @@ def _read_csv(self) -> TextFileReader | DataFrame: | |
| # After _configure_binary_csv_read(), which checks for the header row. | ||
| self._read_csv_header_as_labels(read_csv_kwargs, csv_engine) | ||
| self._csv_converters = read_csv_kwargs.get("converters") or {} | ||
| if csv_engine == "c" and any( | ||
| isinstance(converter, _JSONConverter) | ||
| for converter in self._csv_converters.values() | ||
| ): | ||
| # A NULL placeholder can give internal parser blocks different dtypes. | ||
| read_csv_kwargs.setdefault("low_memory", False) | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Self-review round one (implementation behavior): CLEAN. Full diff:
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Relayed independent review: CLEAN, static source review only. Reviewer: Claude Code
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated to head
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Self-review round one, bounded rebase/documentation follow-up: CLEAN. Previous full range:
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Relayed independent rebase/documentation follow-up: CLEAN, static source review only. Reviewer: Claude Code |
||
| if data is not None: | ||
| # The rows are in memory, with nothing to open with storage options. | ||
| read_csv_kwargs.pop("storage_options", None) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Self-review round two, bounded rebase/documentation follow-up: CLEAN. Reviewed the same literal old/new patch-series comparison as round one; current base/head are
200762088e7b0bac45054f22e32a16aa0ce95dbb/4596cb242cea8a23214f6587c58797ac196fe06a. Checked the revised claims against final converter-map detection and pandas' read-wide low_memory behavior. The docs now state that converter-map membership triggers the default, including unusual parsing overrides that retain an unused JSON converter, and that other inferred columns also receive whole-read dtype inference. Memory cost, preserved requested chunk sizes, and explicit-option precedence remain accurately described. The adjacent upstream DDL/PyArrow explanation is preserved. No new API, positional argument, AWS request, or retry change. Prior measured performance remains explicitly limited to the old head's unchanged local conversion/parser code; the 401-test old-head result is not represented as current-head execution. No findings or deferred claims.